From 839832b4f25d4d612c0e42c5bf00c628fd1bd636 Mon Sep 17 00:00:00 2001 From: asadiqbal Date: Mon, 1 Aug 2016 14:42:03 +0500 Subject: [PATCH] SOL-1868: Receipt page should show the "Go To Dashboard" button in case of non-verified courses --- lms/djangoapps/commerce/tests/test_views.py | 44 ++++++++++++++++++- lms/djangoapps/commerce/urls.py | 3 +- lms/djangoapps/commerce/views.py | 26 ++++++++++- lms/djangoapps/verify_student/views.py | 8 ++-- lms/static/js/commerce/views/receipt_view.js | 35 ++++++++++----- .../js/spec/commerce/receipt_view_spec.js | 5 +++ lms/templates/commerce/receipt.underscore | 2 +- 7 files changed, 103 insertions(+), 20 deletions(-) diff --git a/lms/djangoapps/commerce/tests/test_views.py b/lms/djangoapps/commerce/tests/test_views.py index 50ab358d89..046e2fb432 100644 --- a/lms/djangoapps/commerce/tests/test_views.py +++ b/lms/djangoapps/commerce/tests/test_views.py @@ -3,12 +3,17 @@ from nose.plugins.attrib import attr import ddt +import json from django.core.urlresolvers import reverse from django.test import TestCase import mock from student.tests.factories import UserFactory from openedx.core.djangoapps.theming.tests.test_util import with_comprehensive_theme +from xmodule.modulestore.tests.factories import CourseFactory +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase +from student.models import CourseEnrollment +from course_modes.models import CourseMode class UserMixin(object): @@ -25,9 +30,22 @@ class UserMixin(object): @attr('shard_1') @ddt.ddt -class ReceiptViewTests(UserMixin, TestCase): +class ReceiptViewTests(UserMixin, ModuleStoreTestCase): """ Tests for the receipt view. """ + def setUp(self): + """ + Add a user and a course + """ + super(ReceiptViewTests, self).setUp() + self.user = UserFactory() + self.client.login(username=self.user.username, password='test') + self.course = CourseFactory.create( + org='edX', + course='900', + run='test_run' + ) + def test_login_required(self): """ The view should redirect to the login page if the user is not logged in. """ self.client.logout() @@ -40,6 +58,30 @@ class ReceiptViewTests(UserMixin, TestCase): self.assertEqual(response.status_code, 200) return response + def test_user_verification_status_success(self): + """ + Test user verification status. If the user enrollment for the course belongs to verified modes + e.g. Verified, Professional then verification is required. + """ + # Enroll as verified in the course with the current user. + CourseEnrollment.enroll(self.user, self.course.id, mode=CourseMode.VERIFIED) + response = self.client.get(reverse('commerce:user_verification_status'), data={'course_id': self.course.id}) + json_data = json.loads(response.content) + self.assertEqual(json_data['is_verification_required'], True) + + # Enroll as honor in the course with the current user. + CourseEnrollment.enroll(self.user, self.course.id, mode=CourseMode.HONOR) + response = self.client.get(reverse('commerce:user_verification_status'), data={'course_id': self.course.id}) + json_data = json.loads(response.content) + self.assertEqual(json_data['is_verification_required'], False) + + def test_user_verification_status_failure(self): + """ + Test user verification status failure. View should required HttpResponseBadRequest 400 if course id is missing. + """ + response = self.client.get(reverse('commerce:user_verification_status')) + self.assertEqual(response.status_code, 400) + @ddt.data('decision', 'reason_code', 'signed_field_names', None) def test_is_cybersource(self, post_key): """ diff --git a/lms/djangoapps/commerce/urls.py b/lms/djangoapps/commerce/urls.py index 1ef38c168e..50399b82b5 100644 --- a/lms/djangoapps/commerce/urls.py +++ b/lms/djangoapps/commerce/urls.py @@ -2,7 +2,6 @@ Defines the URL routes for this app. """ from django.conf.urls import patterns, url - from commerce import views @@ -11,4 +10,6 @@ urlpatterns = patterns( url(r'^checkout/cancel/$', views.checkout_cancel, name='checkout_cancel'), url(r'^checkout/error/$', views.checkout_error, name='checkout_error'), url(r'^checkout/receipt/$', views.checkout_receipt, name='checkout_receipt'), + url(r'^checkout/verification_status/$', views.user_verification_status, name='user_verification_status'), + ) diff --git a/lms/djangoapps/commerce/views.py b/lms/djangoapps/commerce/views.py index bf342ac30d..84f2108fe9 100644 --- a/lms/djangoapps/commerce/views.py +++ b/lms/djangoapps/commerce/views.py @@ -13,7 +13,12 @@ from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification from openedx.core.djangoapps.theming.helpers import is_request_in_themed_site from shoppingcart.processors.CyberSource2 import is_user_payment_error from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers - +from opaque_keys.edx.locator import CourseLocator +from student.models import CourseEnrollment +from util.json_request import JsonResponse +from django.views.decorators.http import require_http_methods +from course_modes.models import CourseMode +from django.http import HttpResponseBadRequest log = logging.getLogger(__name__) @@ -96,3 +101,22 @@ def checkout_receipt(request): 'is_request_in_themed_site': is_request_in_themed_site() } return render_to_response('commerce/checkout_receipt.html', context) + + +@require_http_methods(["GET"]) +@login_required +def user_verification_status(request): + """ + Check for user verification status. + :return 'True' if the user enrollment for the course belongs to verified modes e.g. Verified, Professional. + """ + course_id = request.GET.get('course_id', None) + + if course_id is None: + return HttpResponseBadRequest() + + course_key = CourseLocator.from_string(course_id) + enrollment_mode, __ = CourseEnrollment.enrollment_mode_for_user(request.user, course_key) + is_verification_required = enrollment_mode in CourseMode.VERIFIED_MODES + + return JsonResponse({'is_verification_required': is_verification_required}) diff --git a/lms/djangoapps/verify_student/views.py b/lms/djangoapps/verify_student/views.py index 16913613df..12414985c0 100644 --- a/lms/djangoapps/verify_student/views.py +++ b/lms/djangoapps/verify_student/views.py @@ -437,8 +437,8 @@ class PayAndVerifyView(View): return render_to_response("verify_student/pay_and_verify.html", context) def _redirect_if_necessary( - self, message, already_verified, already_paid, is_enrolled, course_key, # pylint: disable=bad-continuation - user_is_trying_to_pay, user, sku # pylint: disable=bad-continuation + self, message, already_verified, already_paid, is_enrolled, course_key, # pylint: disable=bad-continuation + user_is_trying_to_pay, user, sku # pylint: disable=bad-continuation ): """Redirect the user to a more appropriate page if necessary. @@ -497,8 +497,8 @@ class PayAndVerifyView(View): else: url = reverse('verify_student_start_flow', kwargs=course_kwargs) - if user_is_trying_to_pay and user.is_active: - # IIf the user is trying to pay, has activated their account, and the ecommerce service + if user_is_trying_to_pay and user.is_active and not already_paid: + # If the user is trying to pay, has activated their account, and the ecommerce service # is enabled redirect him to the ecommerce checkout page. ecommerce_service = EcommerceService() if ecommerce_service.is_enabled(user): diff --git a/lms/static/js/commerce/views/receipt_view.js b/lms/static/js/commerce/views/receipt_view.js index b32f3156d6..bad5237ef8 100644 --- a/lms/static/js/commerce/views/receipt_view.js +++ b/lms/static/js/commerce/views/receipt_view.js @@ -34,25 +34,36 @@ var edx = edx || {}; // Add the receipt info to the template context this.courseKey = this.getOrderCourseKey(data); this.username = this.$el.data('username'); - _.extend(context, { - receipt: this.receiptContext(data), - courseKey: this.courseKey + var self = this; + $.ajax({ + type: "GET", + url: "/commerce/checkout/verification_status/", + data: { course_id: this.courseKey} + }).success(function(response){ + _.extend(context, { + receipt: self.receiptContext(data), + courseKey: self.courseKey, + is_verification_required: response.is_verification_required + }); - this.$el.html(_.template(templateHtml)(context)); + self.$el.html(_.template(templateHtml)(context)); - this.trackLinks(); + self.trackLinks(); - this.trackPurchase(data); + self.trackPurchase(data); - this.renderCourseNamePlaceholder(this.courseKey); + self.renderCourseNamePlaceholder(self.courseKey); - this.renderUserFullNamePlaceholder(this.username); + self.renderUserFullNamePlaceholder(self.username); - providerId = this.getCreditProviderId(data); - if (providerId) { - this.getProviderData(providerId).then(this.renderProvider, this.renderError) - } + providerId = self.getCreditProviderId(data); + if (providerId) { + self.getProviderData(providerId).then(self.renderProvider, self.renderError); + } + }).error(function(){ + self.renderError(); + }); }, renderCourseNamePlaceholder: function (courseId) { // Display the course Id or name (if available) in the placeholder diff --git a/lms/static/js/spec/commerce/receipt_view_spec.js b/lms/static/js/spec/commerce/receipt_view_spec.js index e86334bc56..b30570e6f1 100644 --- a/lms/static/js/spec/commerce/receipt_view_spec.js +++ b/lms/static/js/spec/commerce/receipt_view_spec.js @@ -36,6 +36,11 @@ define([ view.render(); mockRequests(requests, 'GET', orderUrlFormat, data); + mockRequests( + requests, 'GET', '/commerce/checkout/verification_status/?course_id=' + + encodeURIComponent('course-v1:edx+dummy+2015_T3'), {is_verification_required: true} + ); + mockRequests( requests, 'GET', '/api/courses/v1/courses/course-v1:edx+dummy+2015_T3/', courseResponseData ); diff --git a/lms/templates/commerce/receipt.underscore b/lms/templates/commerce/receipt.underscore index d75e2defc6..9e676007d8 100644 --- a/lms/templates/commerce/receipt.underscore +++ b/lms/templates/commerce/receipt.underscore @@ -88,7 +88,7 @@ <% } %>