Commit eb5e7d89 by Diana Huang

Merge pull request #7094 from edx/diana/add-sku-to-coursemode

Add SKU to Course Modes
parents d39a51a1 3b0bb112
# -*- 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.sku'
db.add_column('course_modes_coursemode', 'sku',
self.gf('django.db.models.fields.CharField')(max_length=255, null=True),
keep_default=False)
def backwards(self, orm):
# Deleting field 'CourseMode.sku'
db.delete_column('course_modes_coursemode', 'sku')
models = {
'course_modes.coursemode': {
'Meta': {'unique_together': "(('course_id', 'mode_slug', 'currency'),)", 'object_name': 'CourseMode'},
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255', 'db_index': 'True'}),
'currency': ('django.db.models.fields.CharField', [], {'default': "'usd'", 'max_length': '8'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'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'}),
'sku': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'suggested_prices': ('django.db.models.fields.CommaSeparatedIntegerField', [], {'default': "''", 'max_length': '255', 'blank': 'True'})
},
'course_modes.coursemodesarchive': {
'Meta': {'object_name': 'CourseModesArchive'},
'course_id': ('xmodule_django.models.CourseKeyField', [], {'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']
...@@ -19,7 +19,8 @@ Mode = namedtuple('Mode', ...@@ -19,7 +19,8 @@ Mode = namedtuple('Mode',
'suggested_prices', 'suggested_prices',
'currency', 'currency',
'expiration_datetime', 'expiration_datetime',
'description' 'description',
'sku',
]) ])
...@@ -56,7 +57,15 @@ class CourseMode(models.Model): ...@@ -56,7 +57,15 @@ class CourseMode(models.Model):
# WARNING: will not be localized # WARNING: will not be localized
description = models.TextField(null=True, blank=True) description = models.TextField(null=True, blank=True)
DEFAULT_MODE = Mode('honor', _('Honor Code Certificate'), 0, '', 'usd', None, None) #optional SKU for Oscar integration
sku = models.CharField(
max_length=255,
null=True,
blank=True,
help_text="This is the SKU(stock keeping unit) of this mode in external services."
)
DEFAULT_MODE = Mode('honor', _('Honor Code Certificate'), 0, '', 'usd', None, None, None)
DEFAULT_MODE_SLUG = 'honor' DEFAULT_MODE_SLUG = 'honor'
# Modes that allow a student to pursue a verified certificate # Modes that allow a student to pursue a verified certificate
...@@ -381,7 +390,8 @@ class CourseMode(models.Model): ...@@ -381,7 +390,8 @@ class CourseMode(models.Model):
self.suggested_prices, self.suggested_prices,
self.currency, self.currency,
self.expiration_datetime, self.expiration_datetime,
self.description self.description,
self.sku
) )
def __unicode__(self): def __unicode__(self):
......
...@@ -53,7 +53,7 @@ class CourseModeModelTest(TestCase): ...@@ -53,7 +53,7 @@ class CourseModeModelTest(TestCase):
self.create_mode('verified', 'Verified Certificate') self.create_mode('verified', 'Verified Certificate')
modes = CourseMode.modes_for_course(self.course_key) modes = CourseMode.modes_for_course(self.course_key)
mode = Mode(u'verified', u'Verified Certificate', 0, '', 'usd', None, None) mode = Mode(u'verified', u'Verified Certificate', 0, '', 'usd', None, None, None)
self.assertEqual([mode], modes) self.assertEqual([mode], modes)
modes_dict = CourseMode.modes_for_course_dict(self.course_key) modes_dict = CourseMode.modes_for_course_dict(self.course_key)
...@@ -65,8 +65,8 @@ class CourseModeModelTest(TestCase): ...@@ -65,8 +65,8 @@ class CourseModeModelTest(TestCase):
""" """
Finding the modes when there's multiple modes Finding the modes when there's multiple modes
""" """
mode1 = Mode(u'honor', u'Honor Code Certificate', 0, '', 'usd', None, None) mode1 = Mode(u'honor', u'Honor Code Certificate', 0, '', 'usd', None, None, None)
mode2 = Mode(u'verified', u'Verified Certificate', 0, '', 'usd', None, None) mode2 = Mode(u'verified', u'Verified Certificate', 0, '', 'usd', None, None, None)
set_modes = [mode1, mode2] set_modes = [mode1, mode2]
for mode in set_modes: for mode in set_modes:
self.create_mode(mode.slug, mode.name, mode.min_price, mode.suggested_prices) self.create_mode(mode.slug, mode.name, mode.min_price, mode.suggested_prices)
...@@ -85,9 +85,9 @@ class CourseModeModelTest(TestCase): ...@@ -85,9 +85,9 @@ class CourseModeModelTest(TestCase):
self.assertEqual(0, CourseMode.min_course_price_for_currency(self.course_key, 'usd')) self.assertEqual(0, CourseMode.min_course_price_for_currency(self.course_key, 'usd'))
# create some modes # create some modes
mode1 = Mode(u'honor', u'Honor Code Certificate', 10, '', 'usd', None, None) mode1 = Mode(u'honor', u'Honor Code Certificate', 10, '', 'usd', None, None, None)
mode2 = Mode(u'verified', u'Verified Certificate', 20, '', 'usd', None, None) mode2 = Mode(u'verified', u'Verified Certificate', 20, '', 'usd', None, None, None)
mode3 = Mode(u'honor', u'Honor Code Certificate', 80, '', 'cny', None, None) mode3 = Mode(u'honor', u'Honor Code Certificate', 80, '', 'cny', None, None, None)
set_modes = [mode1, mode2, mode3] set_modes = [mode1, mode2, mode3]
for mode in set_modes: for mode in set_modes:
self.create_mode(mode.slug, mode.name, mode.min_price, mode.suggested_prices, mode.currency) self.create_mode(mode.slug, mode.name, mode.min_price, mode.suggested_prices, mode.currency)
...@@ -102,7 +102,7 @@ class CourseModeModelTest(TestCase): ...@@ -102,7 +102,7 @@ class CourseModeModelTest(TestCase):
modes = CourseMode.modes_for_course(self.course_key) modes = CourseMode.modes_for_course(self.course_key)
self.assertEqual([CourseMode.DEFAULT_MODE], modes) self.assertEqual([CourseMode.DEFAULT_MODE], modes)
mode1 = Mode(u'honor', u'Honor Code Certificate', 0, '', 'usd', None, None) mode1 = Mode(u'honor', u'Honor Code Certificate', 0, '', 'usd', None, None, None)
self.create_mode(mode1.slug, mode1.name, mode1.min_price, mode1.suggested_prices) self.create_mode(mode1.slug, mode1.name, mode1.min_price, mode1.suggested_prices)
modes = CourseMode.modes_for_course(self.course_key) modes = CourseMode.modes_for_course(self.course_key)
self.assertEqual([mode1], modes) self.assertEqual([mode1], modes)
...@@ -110,7 +110,7 @@ class CourseModeModelTest(TestCase): ...@@ -110,7 +110,7 @@ class CourseModeModelTest(TestCase):
expiration_datetime = datetime.now(pytz.UTC) + timedelta(days=1) expiration_datetime = datetime.now(pytz.UTC) + timedelta(days=1)
expired_mode.expiration_datetime = expiration_datetime expired_mode.expiration_datetime = expiration_datetime
expired_mode.save() expired_mode.save()
expired_mode_value = Mode(u'verified', u'Verified Certificate', 0, '', 'usd', expiration_datetime, None) expired_mode_value = Mode(u'verified', u'Verified Certificate', 0, '', 'usd', expiration_datetime, None, None)
modes = CourseMode.modes_for_course(self.course_key) modes = CourseMode.modes_for_course(self.course_key)
self.assertEqual([expired_mode_value, mode1], modes) self.assertEqual([expired_mode_value, mode1], modes)
......
...@@ -230,7 +230,7 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase): ...@@ -230,7 +230,7 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase):
self.assertEquals(response.status_code, 200) self.assertEquals(response.status_code, 200)
expected_mode = [Mode(u'honor', u'Honor Code Certificate', 0, '', 'usd', None, None)] expected_mode = [Mode(u'honor', u'Honor Code Certificate', 0, '', 'usd', None, None, None)]
course_mode = CourseMode.modes_for_course(self.course.id) course_mode = CourseMode.modes_for_course(self.course.id)
self.assertEquals(course_mode, expected_mode) self.assertEquals(course_mode, expected_mode)
...@@ -254,7 +254,7 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase): ...@@ -254,7 +254,7 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase):
self.assertEquals(response.status_code, 200) self.assertEquals(response.status_code, 200)
expected_mode = [Mode(mode_slug, mode_display_name, min_price, suggested_prices, currency, None, None)] expected_mode = [Mode(mode_slug, mode_display_name, min_price, suggested_prices, currency, None, None, None)]
course_mode = CourseMode.modes_for_course(self.course.id) course_mode = CourseMode.modes_for_course(self.course.id)
self.assertEquals(course_mode, expected_mode) self.assertEquals(course_mode, expected_mode)
...@@ -277,8 +277,8 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase): ...@@ -277,8 +277,8 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase):
url = reverse('create_mode', args=[unicode(self.course.id)]) url = reverse('create_mode', args=[unicode(self.course.id)])
self.client.get(url, parameters) self.client.get(url, parameters)
honor_mode = Mode(u'honor', u'Honor Code Certificate', 0, '', 'usd', None, None) honor_mode = Mode(u'honor', u'Honor Code Certificate', 0, '', 'usd', None, None, None)
verified_mode = Mode(u'verified', u'Verified Certificate', 10, '10,20', 'usd', None, None) verified_mode = Mode(u'verified', u'Verified Certificate', 10, '10,20', 'usd', None, None, None)
expected_modes = [honor_mode, verified_mode] expected_modes = [honor_mode, verified_mode]
course_modes = CourseMode.modes_for_course(self.course.id) course_modes = CourseMode.modes_for_course(self.course.id)
......
...@@ -45,7 +45,8 @@ def get_enrollments(user_id): ...@@ -45,7 +45,8 @@ def get_enrollments(user_id):
"suggested_prices": "", "suggested_prices": "",
"currency": "usd", "currency": "usd",
"expiration_datetime": null, "expiration_datetime": null,
"description": null "description": null,
"sku": null
} }
], ],
"enrollment_start": 2014-10-15T20:18:00Z, "enrollment_start": 2014-10-15T20:18:00Z,
...@@ -68,7 +69,8 @@ def get_enrollments(user_id): ...@@ -68,7 +69,8 @@ def get_enrollments(user_id):
"suggested_prices": "", "suggested_prices": "",
"currency": "usd", "currency": "usd",
"expiration_datetime": null, "expiration_datetime": null,
"description": null "description": null,
"sku": null
} }
], ],
"enrollment_start": 2014-10-15T20:18:00Z, "enrollment_start": 2014-10-15T20:18:00Z,
...@@ -111,7 +113,8 @@ def get_enrollment(user_id, course_id): ...@@ -111,7 +113,8 @@ def get_enrollment(user_id, course_id):
"suggested_prices": "", "suggested_prices": "",
"currency": "usd", "currency": "usd",
"expiration_datetime": null, "expiration_datetime": null,
"description": null "description": null,
"sku": null
} }
], ],
"enrollment_start": 2014-10-15T20:18:00Z, "enrollment_start": 2014-10-15T20:18:00Z,
...@@ -157,7 +160,8 @@ def add_enrollment(user_id, course_id, mode='honor', is_active=True): ...@@ -157,7 +160,8 @@ def add_enrollment(user_id, course_id, mode='honor', is_active=True):
"suggested_prices": "", "suggested_prices": "",
"currency": "usd", "currency": "usd",
"expiration_datetime": null, "expiration_datetime": null,
"description": null "description": null,
"sku": null
} }
], ],
"enrollment_start": 2014-10-15T20:18:00Z, "enrollment_start": 2014-10-15T20:18:00Z,
...@@ -201,7 +205,8 @@ def update_enrollment(user_id, course_id, mode=None, is_active=None): ...@@ -201,7 +205,8 @@ def update_enrollment(user_id, course_id, mode=None, is_active=None):
"suggested_prices": "", "suggested_prices": "",
"currency": "usd", "currency": "usd",
"expiration_datetime": null, "expiration_datetime": null,
"description": null "description": null,
"sku": null
} }
], ],
"enrollment_start": 2014-10-15T20:18:00Z, "enrollment_start": 2014-10-15T20:18:00Z,
...@@ -243,7 +248,8 @@ def get_course_enrollment_details(course_id): ...@@ -243,7 +248,8 @@ def get_course_enrollment_details(course_id):
"suggested_prices": "", "suggested_prices": "",
"currency": "usd", "currency": "usd",
"expiration_datetime": null, "expiration_datetime": null,
"description": null "description": null,
"sku": null
} }
], ],
"enrollment_start": 2014-10-15T20:18:00Z, "enrollment_start": 2014-10-15T20:18:00Z,
......
...@@ -85,3 +85,4 @@ class ModeSerializer(serializers.Serializer): ...@@ -85,3 +85,4 @@ class ModeSerializer(serializers.Serializer):
currency = serializers.CharField(max_length=8) currency = serializers.CharField(max_length=8)
expiration_datetime = serializers.DateTimeField() expiration_datetime = serializers.DateTimeField()
description = serializers.CharField() description = serializers.CharField()
sku = serializers.CharField()
...@@ -206,6 +206,7 @@ class EnrollmentTest(ModuleStoreTestCase, APITestCase): ...@@ -206,6 +206,7 @@ class EnrollmentTest(ModuleStoreTestCase, APITestCase):
course_id=self.course.id, course_id=self.course.id,
mode_slug='honor', mode_slug='honor',
mode_display_name='Honor', mode_display_name='Honor',
sku='123',
) )
resp = self.client.get( resp = self.client.get(
reverse('courseenrollmentdetails', kwargs={"course_id": unicode(self.course.id)}) reverse('courseenrollmentdetails', kwargs={"course_id": unicode(self.course.id)})
...@@ -214,6 +215,10 @@ class EnrollmentTest(ModuleStoreTestCase, APITestCase): ...@@ -214,6 +215,10 @@ class EnrollmentTest(ModuleStoreTestCase, APITestCase):
data = json.loads(resp.content) data = json.loads(resp.content)
self.assertEqual(unicode(self.course.id), data['course_id']) self.assertEqual(unicode(self.course.id), data['course_id'])
mode = data['course_modes'][0]
self.assertEqual(mode['slug'], 'honor')
self.assertEqual(mode['sku'], '123')
self.assertEqual(mode['name'], 'Honor')
def test_with_invalid_course_id(self): def test_with_invalid_course_id(self):
self._create_enrollment(course_id='entirely/fake/course', expected_status=status.HTTP_400_BAD_REQUEST) self._create_enrollment(course_id='entirely/fake/course', expected_status=status.HTTP_400_BAD_REQUEST)
......
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