commerce/api: Don’t allow setting expiration of prof modes.
XCOM-497
This commit is contained in:
@@ -4,6 +4,7 @@ Add and create new modes for running courses on this particular LMS
|
||||
import pytz
|
||||
from datetime import datetime
|
||||
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from collections import namedtuple, defaultdict
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
@@ -106,8 +107,19 @@ class CourseMode(models.Model):
|
||||
""" meta attributes of this model """
|
||||
unique_together = ('course_id', 'mode_slug', 'currency')
|
||||
|
||||
def clean(self):
|
||||
"""
|
||||
Object-level validation - implemented in this method so DRF serializers
|
||||
catch errors in advance of a save() attempt.
|
||||
"""
|
||||
if self.is_professional_slug(self.mode_slug) and self.expiration_datetime is not None:
|
||||
raise ValidationError(
|
||||
_(u"Professional education modes are not allowed to have expiration_datetime set.")
|
||||
)
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None):
|
||||
# Ensure currency is always lowercase.
|
||||
self.clean() # ensure object-level validation is performed before we save.
|
||||
self.currency = self.currency.lower()
|
||||
super(CourseMode, self).save(force_insert, force_update, using)
|
||||
|
||||
|
||||
@@ -6,12 +6,15 @@ Replace this with more appropriate tests for your application.
|
||||
"""
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
import pytz
|
||||
import ddt
|
||||
import itertools
|
||||
|
||||
import ddt
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.test import TestCase
|
||||
from opaque_keys.edx.locations import SlashSeparatedCourseKey
|
||||
from opaque_keys.edx.locator import CourseLocator
|
||||
from django.test import TestCase
|
||||
import pytz
|
||||
|
||||
from course_modes.models import CourseMode, Mode
|
||||
|
||||
|
||||
@@ -26,7 +29,15 @@ class CourseModeModelTest(TestCase):
|
||||
self.course_key = SlashSeparatedCourseKey('Test', 'TestCourse', 'TestCourseRun')
|
||||
CourseMode.objects.all().delete()
|
||||
|
||||
def create_mode(self, mode_slug, mode_name, min_price=0, suggested_prices='', currency='usd'):
|
||||
def create_mode(
|
||||
self,
|
||||
mode_slug,
|
||||
mode_name,
|
||||
min_price=0,
|
||||
suggested_prices='',
|
||||
currency='usd',
|
||||
expiration_datetime=None,
|
||||
):
|
||||
"""
|
||||
Create a new course mode
|
||||
"""
|
||||
@@ -37,6 +48,7 @@ class CourseModeModelTest(TestCase):
|
||||
min_price=min_price,
|
||||
suggested_prices=suggested_prices,
|
||||
currency=currency,
|
||||
expiration_datetime=expiration_datetime,
|
||||
)
|
||||
|
||||
def test_save(self):
|
||||
@@ -264,6 +276,29 @@ class CourseModeModelTest(TestCase):
|
||||
else:
|
||||
self.assertFalse(CourseMode.is_verified_slug(mode_slug))
|
||||
|
||||
@ddt.data(*itertools.product(
|
||||
(
|
||||
CourseMode.HONOR,
|
||||
CourseMode.AUDIT,
|
||||
CourseMode.VERIFIED,
|
||||
CourseMode.PROFESSIONAL,
|
||||
CourseMode.NO_ID_PROFESSIONAL_MODE
|
||||
),
|
||||
(datetime.now(), None),
|
||||
))
|
||||
@ddt.unpack
|
||||
def test_invalid_mode_expiration(self, mode_slug, exp_dt):
|
||||
is_error_expected = CourseMode.is_professional_slug(mode_slug) and exp_dt is not None
|
||||
try:
|
||||
self.create_mode(mode_slug=mode_slug, mode_name=mode_slug.title(), expiration_datetime=exp_dt)
|
||||
self.assertFalse(is_error_expected, "Expected a ValidationError to be thrown.")
|
||||
except ValidationError, exc:
|
||||
self.assertTrue(is_error_expected, "Did not expect a ValidationError to be thrown.")
|
||||
self.assertEqual(
|
||||
exc.messages,
|
||||
[u"Professional education modes are not allowed to have expiration_datetime set."],
|
||||
)
|
||||
|
||||
@ddt.data(
|
||||
("verified", "verify_need_to_verify"),
|
||||
("verified", "verify_submitted"),
|
||||
|
||||
Reference in New Issue
Block a user