Commit fc468bf6 by Diana Huang

Set up basic enrollment infrastructure.

parent 471f5135
......@@ -31,6 +31,7 @@ class CourseModeViewTest(ModuleStoreTestCase):
self.user = UserFactory.create(username="Bob", email="bob@example.com", password="edx")
self.client.login(username=self.user.username, password="edx")
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
@ddt.data(
# is_active?, enrollment_mode, upgrade?, redirect?
(True, 'verified', True, False), # User has an active verified enrollment and is trying to upgrade
......
......@@ -26,10 +26,10 @@ class ChooseModeView(View):
When a get request is used, shows the selection page.
When a post request is used, assumes that it is a form submission
When a post request is used, assumes that it is a form submission
from the selection page, parses the response, and then sends user
to the next step in the flow.
"""
@method_decorator(login_required)
......@@ -50,7 +50,7 @@ class ChooseModeView(View):
"""
course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
enrollment_mode, is_active = CourseEnrollment.enrollment_mode_for_user(request.user, course_key)
upgrade = request.GET.get('upgrade', False)
request.session['attempting_upgrade'] = upgrade
......
......@@ -73,7 +73,7 @@ def update_course_enrollment(student_id, course_id, mode=None, is_active=None):
course_key = CourseKey.from_string(course_id)
student = User.objects.get(username=student_id)
if not CourseEnrollment.is_enrolled(student, course_key):
enrollment = CourseEnrollment.enroll(student, course_key)
enrollment = CourseEnrollment.enroll(student, course_key, check_access=True)
else:
enrollment = CourseEnrollment.objects.get(user=student, course_id=course_key)
......
......@@ -10,7 +10,7 @@ from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.throttling import UserRateThrottle
from enrollment import api
from student.models import NonExistentCourseError
from student.models import NonExistentCourseError, CourseEnrollmentException
class EnrollmentUserThrottle(UserRateThrottle):
......@@ -74,3 +74,5 @@ def get_course_enrollment(request, course_id=None):
return Response(status=status.HTTP_400_BAD_REQUEST)
except api.EnrollmentNotFoundError:
return Response(status=status.HTTP_400_BAD_REQUEST)
except CourseEnrollmentException:
return Response(status=status.HTTP_400_BAD_REQUEST)
......@@ -1028,6 +1028,7 @@ instructor_dash_js = sorted(rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/ins
student_account_js = [
'js/common_helpers/rwd_header_footer.js',
'js/common_helpers/edx.utils.validate.js',
'js/student_account/enrollment_interface.js',
'js/student_account/models/LoginModel.js',
'js/student_account/models/RegisterModel.js',
'js/student_account/models/PasswordResetModel.js',
......
define(['js/common_helpers/template_helpers', 'js/student_account/enrollment_interface'],
function(TemplateHelpers) {
describe("edx.student.account.EnrollmentInterface", function() {
'use strict';
it("find course modes using modeInArray ", function() {
var course_modes = [
{
},
{
}
];
});
});
}
);
......@@ -39,6 +39,10 @@ define(['js/common_helpers/template_helpers', 'js/student_account/views/LoginVie
it("allows the user to navigate to the password assistance form", function() {
// TODO
});
it("enrolls the student into the right location and forwards them properly", function() {
// TODO
});
});
}
);
var edx = edx || {};
(function($, _, gettext) {
'use strict';
edx.student = edx.student || {};
edx.student.account = edx.student.account || {};
edx.student.account.EnrollmentInterface = {
courseUrl: '/enrollment/v0/course/',
studentUrl: '/enrollment/v0/student',
trackSelectionUrl: '/course_modes/choose/',
headers: {
'X-CSRFToken': $.cookie('csrftoken')
},
studentInformation: function(course_key) {
// retrieve student enrollment information
},
courseInformation: function(course_key) {
// retrieve course information from the enrollment API
},
modeInArray: function(mode_slug, course_modes) {
// finds whether or not a particular course mode slug exists
// in an array of course modes
var result = _.find(course_modes, function(mode){ return mode.slug === mode_slug; });
return result != undefined;
},
enroll: function(course_key, forward_url){
var me = this;
// attempt to enroll a student in a course
$.ajax({
url: this.courseUrl + course_key,
type: 'POST',
data: {},
headers: this.headers
}).done(function(data){
me.postEnrollmentHandler(course_key, data, forward_url);
}
).fail(function(data, textStatus) {
me.enrollmentFailureHandler(course_key, data, forward_url);
});
},
enrollmentFailureHandler: function(course_key, data, forward_url) {
// handle failures to enroll via the API
if(data.status == 400) {
// This status code probably means we don't have permissions to register for this course.
// look at the contents of the response
var course = $.parseJSON(data.responseText);
// see if it's a professional ed course
if('course_modes' in course && this.modeInArray('professional', course.course_modes)) {
// forward appropriately
forward_url = this.trackSelectionUrl + course_key;
}
}
// TODO: if we have a paid registration mode, add item to the cart and send them along
// TODO: we should figure out how to handle errors here eventually
window.location.href = forward_url;
},
postEnrollmentHandler: function(course_key, data, forward_url) {
// Determine whether or not the course needs to be redirected to
// a particular page.
var course = data.course,
course_modes = course.course_modes;
// send the user to the track selection page, because it will do the right thing
forward_url = this.trackSelectionUrl + course_key;
window.location.href = forward_url;
}
};
})(jQuery, _, gettext);
......@@ -6,6 +6,7 @@ var edx = edx || {};
edx.student = edx.student || {};
edx.student.account = edx.student.account || {};
edx.student.account.LoginModel = Backbone.Model.extend({
defaults: {
......@@ -32,17 +33,31 @@ var edx = edx || {};
headers: headers
})
.done(function() {
var query = window.location.search,
url = '/dashboard';
var enrollment = edx.student.account.EnrollmentInterface,
query = new URI(window.location.search),
url = '/dashboard',
query_map = query.search(true),
next = '';
// check for forwarding url
if("next" in query_map) {
next = query_map['next'];
if(!window.isExternal(next)){
url = next;
}
}
model.trigger('sync');
// If query string in url go back to that page
if ( query.length > 1 ) {
url = query.substring( query.indexOf('=') + 1 );
// if we need to enroll in the course, mark as enrolled
if('enrollment_action' in query_map && query_map['enrollment_action'] === 'enroll'){
enrollment.enroll(query_map['course_id'], url);
}
else {
window.location.href = url;
}
window.location.href = url;
})
.fail( function( error ) {
model.trigger('error', error);
......
......@@ -39,17 +39,29 @@ var edx = edx || {};
headers: headers
})
.done(function() {
var query = window.location.search,
url = '/dashboard';
var enrollment = edx.student.account.EnrollmentInterface,
query = new URI(window.location.search),
url = '/dashboard',
query_map = query.search(true),
next = '';
// check for forwarding url
if("next" in query_map) {
next = query_map['next'];
if(!window.isExternal(next)){
url = next;
}
}
model.trigger('sync');
// If query string in url go back to that page
if ( query.length > 1 ) {
url = query.substring( query.indexOf('=') + 1 );
// if we need to enroll in the course, mark as enrolled
if('enrollment_action' in query_map && query_map['enrollment_action'] === 'enroll'){
enrollment.enroll(query_map['course_id'], url);
}
else {
window.location.href = url;
}
window.location.href = url;
})
.fail( function( error ) {
model.trigger('error', error);
......
......@@ -8,6 +8,7 @@
<%block name="js_extra">
<script type="text/javascript" src="${static.url('js/vendor/backbone-min.js')}"></script>
<script type="text/javascript" src="${static.url('js/vendor/underscore.string.min.js')}"></script>
<script type="text/javascript" src="${static.url('js/vendor/URI.min.js')}"></script>
<%static:js group='student_account'/>
</%block>
......
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