Merge pull request #21252 from edx/ddumesnil/disco-1222
DISCO-1222: Allow switching course numbers for reruns
This commit is contained in:
@@ -8,6 +8,7 @@ import six
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.db import transaction
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from opaque_keys import InvalidKeyError
|
||||
from rest_framework import serializers
|
||||
from rest_framework.fields import empty
|
||||
|
||||
@@ -168,29 +169,40 @@ class CourseRunCreateSerializer(CourseRunSerializer):
|
||||
class CourseRunRerunSerializer(CourseRunSerializerCommonFieldsMixin, CourseRunTeamSerializerMixin,
|
||||
serializers.Serializer):
|
||||
title = serializers.CharField(source='display_name', required=False)
|
||||
number = serializers.CharField(source='id.course', required=False)
|
||||
run = serializers.CharField(source='id.run')
|
||||
|
||||
def validate_run(self, value):
|
||||
def validate(self, attrs):
|
||||
course_run_key = self.instance.id
|
||||
_id = attrs.get('id')
|
||||
number = _id.get('course', course_run_key.course)
|
||||
run = _id['run']
|
||||
store = modulestore()
|
||||
with store.default_store('split'):
|
||||
new_course_run_key = store.make_course_key(course_run_key.org, course_run_key.course, value)
|
||||
try:
|
||||
with store.default_store('split'):
|
||||
new_course_run_key = store.make_course_key(course_run_key.org, number, run)
|
||||
except InvalidKeyError:
|
||||
raise serializers.ValidationError(
|
||||
u'Invalid key supplied. Ensure there are no special characters in the Course Number.'
|
||||
)
|
||||
if store.has_course(new_course_run_key, ignore_case=True):
|
||||
raise serializers.ValidationError(u'Course run {key} already exists'.format(key=new_course_run_key))
|
||||
return value
|
||||
raise serializers.ValidationError(
|
||||
{'run': u'Course run {key} already exists'.format(key=new_course_run_key)}
|
||||
)
|
||||
return attrs
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
course_run_key = instance.id
|
||||
_id = validated_data.pop('id')
|
||||
number = _id.get('course', course_run_key.course)
|
||||
run = _id['run']
|
||||
team = validated_data.pop('team', [])
|
||||
user = self.context['request'].user
|
||||
fields = {
|
||||
'display_name': instance.display_name
|
||||
}
|
||||
fields.update(validated_data)
|
||||
new_course_run_key = rerun_course(
|
||||
user, course_run_key, course_run_key.org, course_run_key.course, _id['run'], fields, False
|
||||
)
|
||||
new_course_run_key = rerun_course(user, course_run_key, course_run_key.org, number, run, fields, False)
|
||||
|
||||
course_run = get_course_and_check_access(new_course_run_key, user)
|
||||
self.update_team(course_run, team)
|
||||
|
||||
@@ -321,18 +321,18 @@ class CourseRunViewSetTests(ModuleStoreTestCase):
|
||||
contentstore().find(content_key)
|
||||
|
||||
@ddt.data(
|
||||
('instructor_paced', False),
|
||||
('self_paced', True),
|
||||
('instructor_paced', False, 'NotOriginalNumber1x'),
|
||||
('self_paced', True, None),
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_rerun(self, pacing_type, expected_self_paced_value):
|
||||
course_run = ToyCourseFactory()
|
||||
def test_rerun(self, pacing_type, expected_self_paced_value, number):
|
||||
original_course_run = ToyCourseFactory()
|
||||
start = datetime.datetime.now(pytz.UTC).replace(microsecond=0)
|
||||
end = start + datetime.timedelta(days=30)
|
||||
user = UserFactory()
|
||||
role = 'instructor'
|
||||
run = '3T2017'
|
||||
url = reverse('api:v1:course_run-rerun', kwargs={'pk': str(course_run.id)})
|
||||
url = reverse('api:v1:course_run-rerun', kwargs={'pk': str(original_course_run.id)})
|
||||
data = {
|
||||
'run': run,
|
||||
'schedule': {
|
||||
@@ -347,13 +347,25 @@ class CourseRunViewSetTests(ModuleStoreTestCase):
|
||||
],
|
||||
'pacing_type': pacing_type,
|
||||
}
|
||||
# If number is supplied, this should become the course number used in the course run key
|
||||
# If not, it should default to the original course run number that the rerun is based on.
|
||||
if number:
|
||||
data.update({'number': number})
|
||||
response = self.client.post(url, data, format='json')
|
||||
assert response.status_code == 201
|
||||
|
||||
course_run_key = CourseKey.from_string(response.data['id'])
|
||||
course_run = modulestore().get_course(course_run_key)
|
||||
|
||||
assert course_run.id.run == run
|
||||
assert course_run.self_paced is expected_self_paced_value
|
||||
|
||||
if number:
|
||||
assert course_run.id.course == number
|
||||
assert course_run.id.course != original_course_run.id.course
|
||||
else:
|
||||
assert course_run.id.course == original_course_run.id.course
|
||||
|
||||
self.assert_course_run_schedule(course_run, start, end)
|
||||
self.assert_access_role(course_run, user, role)
|
||||
self.assert_course_access_role_count(course_run, 1)
|
||||
@@ -367,3 +379,16 @@ class CourseRunViewSetTests(ModuleStoreTestCase):
|
||||
response = self.client.post(url, data, format='json')
|
||||
assert response.status_code == 400
|
||||
assert response.data == {'run': [u'Course run {key} already exists'.format(key=course_run.id)]}
|
||||
|
||||
def test_rerun_invalid_number(self):
|
||||
course_run = ToyCourseFactory()
|
||||
url = reverse('api:v1:course_run-rerun', kwargs={'pk': str(course_run.id)})
|
||||
data = {
|
||||
'run': '2T2019',
|
||||
'number': '!@#$%^&*()',
|
||||
}
|
||||
response = self.client.post(url, data, format='json')
|
||||
assert response.status_code == 400
|
||||
assert response.data == {'non_field_errors': [
|
||||
u'Invalid key supplied. Ensure there are no special characters in the Course Number.'
|
||||
]}
|
||||
|
||||
Reference in New Issue
Block a user