Merge pull request #7372 from edx/clintonb/no-honor-mode-fix
Fixed bug for courses without an honor mode
This commit is contained in:
@@ -19,3 +19,4 @@ class Messages(object):
|
||||
NO_SKU_ENROLLED = u'The {enrollment_mode} mode for {course_id} does not have a SKU. Enrolling {username} directly.'
|
||||
ORDER_COMPLETED = u'Order {order_number} was completed.'
|
||||
ORDER_INCOMPLETE_ENROLLED = u'Order {order_number} was created, but is not yet complete. User was enrolled.'
|
||||
NO_HONOR_MODE = u'Course {course_id} does not have an honor mode.'
|
||||
|
||||
@@ -237,7 +237,6 @@ class OrdersViewTests(ModuleStoreTestCase):
|
||||
response = self._post_to_view()
|
||||
|
||||
# Validate the response
|
||||
self._mock_ecommerce_api()
|
||||
self.assertEqual(response.status_code, 200)
|
||||
msg = Messages.NO_ECOM_API.format(username=self.user.username, course_id=self.course.id)
|
||||
self.assertResponseMessage(response, msg)
|
||||
@@ -245,3 +244,29 @@ class OrdersViewTests(ModuleStoreTestCase):
|
||||
# Ensure that the user is not enrolled and that no calls were made to the E-Commerce API
|
||||
self.assertTrue(CourseEnrollment.is_enrolled(self.user, self.course.id))
|
||||
self.assertIsInstance(httpretty.last_request(), HTTPrettyRequestEmpty)
|
||||
|
||||
def _test_professional_mode_only(self):
|
||||
""" Verifies that the view behaves appropriately when the course only has a professional mode. """
|
||||
CourseMode.objects.filter(course_id=self.course.id).delete()
|
||||
mode = 'no-id-professional'
|
||||
CourseModeFactory.create(course_id=self.course.id, mode_slug=mode, mode_display_name=mode,
|
||||
sku=uuid4().hex.decode('ascii'))
|
||||
self._mock_ecommerce_api()
|
||||
response = self._post_to_view()
|
||||
self.assertEqual(response.status_code, 406)
|
||||
msg = Messages.NO_HONOR_MODE.format(course_id=self.course.id)
|
||||
self.assertResponseMessage(response, msg)
|
||||
|
||||
@httpretty.activate
|
||||
def test_course_with_professional_mode_only(self):
|
||||
""" Verifies that the view behaves appropriately when the course only has a professional mode. """
|
||||
self._test_professional_mode_only()
|
||||
|
||||
@httpretty.activate
|
||||
@override_settings(ECOMMERCE_API_URL=None, ECOMMERCE_API_SIGNING_KEY=None)
|
||||
def test_no_settings_and_professional_mode_only(self):
|
||||
"""
|
||||
Verifies that the view behaves appropriately when the course only has a professional mode and
|
||||
the E-Commerce API is not configured.
|
||||
"""
|
||||
self._test_professional_mode_only()
|
||||
|
||||
@@ -79,28 +79,33 @@ class OrdersView(APIView):
|
||||
if not valid:
|
||||
return DetailResponse(error, status=HTTP_406_NOT_ACCEPTABLE)
|
||||
|
||||
# Ensure that the course has an honor mode with SKU
|
||||
honor_mode = CourseMode.mode_for_course(course_key, CourseMode.HONOR)
|
||||
course_id = unicode(course_key)
|
||||
|
||||
# If there is no honor course mode, this most likely a Prof-Ed course. Return an error so that the JS
|
||||
# redirects to track selection.
|
||||
if not honor_mode:
|
||||
msg = Messages.NO_HONOR_MODE.format(course_id=course_id)
|
||||
return DetailResponse(msg, status=HTTP_406_NOT_ACCEPTABLE)
|
||||
elif not honor_mode.sku:
|
||||
# If there are no course modes with SKUs, enroll the user without contacting the external API.
|
||||
msg = Messages.NO_SKU_ENROLLED.format(enrollment_mode=CourseMode.HONOR, course_id=course_id,
|
||||
username=user.username)
|
||||
log.debug(msg)
|
||||
self._enroll(course_key, user)
|
||||
return DetailResponse(msg)
|
||||
|
||||
# Ensure that the E-Commerce API is setup properly
|
||||
ecommerce_api_url = getattr(settings, 'ECOMMERCE_API_URL', None)
|
||||
ecommerce_api_signing_key = getattr(settings, 'ECOMMERCE_API_SIGNING_KEY', None)
|
||||
|
||||
if not (ecommerce_api_url and ecommerce_api_signing_key):
|
||||
self._enroll(course_key, user)
|
||||
msg = Messages.NO_ECOM_API.format(username=user.username, course_id=unicode(course_key))
|
||||
msg = Messages.NO_ECOM_API.format(username=user.username, course_id=course_id)
|
||||
log.debug(msg)
|
||||
return DetailResponse(msg)
|
||||
|
||||
# Default to honor mode. In the future we may expand this view to support additional modes.
|
||||
mode = CourseMode.DEFAULT_MODE_SLUG
|
||||
course_modes = CourseMode.objects.filter(course_id=course_key, mode_slug=mode, sku__isnull=False)
|
||||
|
||||
# If there are no course modes with SKUs, enroll the user without contacting the external API.
|
||||
if not course_modes.exists():
|
||||
msg = Messages.NO_SKU_ENROLLED.format(enrollment_mode=mode, course_id=unicode(course_key),
|
||||
username=user.username)
|
||||
log.debug(msg)
|
||||
self._enroll(course_key, user)
|
||||
return DetailResponse(msg)
|
||||
|
||||
# Contact external API
|
||||
headers = {
|
||||
'Content-Type': 'application/json',
|
||||
@@ -111,7 +116,7 @@ class OrdersView(APIView):
|
||||
|
||||
try:
|
||||
timeout = getattr(settings, 'ECOMMERCE_API_TIMEOUT', 5)
|
||||
response = requests.post(url, data=json.dumps({'sku': course_modes[0].sku}), headers=headers,
|
||||
response = requests.post(url, data=json.dumps({'sku': honor_mode.sku}), headers=headers,
|
||||
timeout=timeout)
|
||||
except Exception as ex: # pylint: disable=broad-except
|
||||
log.exception('Call to E-Commerce API failed: %s.', ex.message)
|
||||
@@ -143,7 +148,7 @@ class OrdersView(APIView):
|
||||
'status': order_status,
|
||||
'complete_status': OrderStatus.COMPLETE,
|
||||
'username': user.username,
|
||||
'course_id': unicode(course_key),
|
||||
'course_id': course_id,
|
||||
}
|
||||
log.error(msg, msg_kwargs)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user