diff --git a/common/djangoapps/course_modes/admin.py b/common/djangoapps/course_modes/admin.py index 124f7ba..a500d5c 100644 --- a/common/djangoapps/course_modes/admin.py +++ b/common/djangoapps/course_modes/admin.py @@ -184,7 +184,8 @@ class CourseModeAdmin(admin.ModelAdmin): 'currency', '_expiration_datetime', 'verification_deadline', - 'sku' + 'sku', + 'bulk_sku' ) search_fields = ('course_id',) @@ -195,7 +196,8 @@ class CourseModeAdmin(admin.ModelAdmin): 'mode_slug', 'min_price', 'expiration_datetime_custom', - 'sku' + 'sku', + 'bulk_sku' ) def expiration_datetime_custom(self, obj): diff --git a/common/djangoapps/course_modes/migrations/0007_coursemode_bulk_sku.py b/common/djangoapps/course_modes/migrations/0007_coursemode_bulk_sku.py new file mode 100644 index 0000000..dbb086f --- /dev/null +++ b/common/djangoapps/course_modes/migrations/0007_coursemode_bulk_sku.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('course_modes', '0006_auto_20160208_1407'), + ] + + operations = [ + migrations.AddField( + model_name='coursemode', + name='bulk_sku', + field=models.CharField(help_text='This is the bulk SKU (stock keeping unit) of this mode in the external ecommerce service.', max_length=255, null=True, verbose_name=b'Bulk SKU', blank=True), + ), + ] diff --git a/common/djangoapps/course_modes/models.py b/common/djangoapps/course_modes/models.py index 3bfe45c..f90079c 100644 --- a/common/djangoapps/course_modes/models.py +++ b/common/djangoapps/course_modes/models.py @@ -22,6 +22,7 @@ Mode = namedtuple('Mode', 'expiration_datetime', 'description', 'sku', + 'bulk_sku', ]) @@ -96,6 +97,17 @@ class CourseMode(models.Model): ) ) + # Optional bulk order SKU for integration with the ecommerce service + bulk_sku = models.CharField( + max_length=255, + null=True, + blank=True, + verbose_name="Bulk SKU", + help_text=_( + u"This is the bulk SKU (stock keeping unit) of this mode in the external ecommerce service." + ) + ) + HONOR = 'honor' PROFESSIONAL = 'professional' VERIFIED = "verified" @@ -103,7 +115,7 @@ class CourseMode(models.Model): NO_ID_PROFESSIONAL_MODE = "no-id-professional" CREDIT_MODE = "credit" - DEFAULT_MODE = Mode(AUDIT, _('Audit'), 0, '', 'usd', None, None, None) + DEFAULT_MODE = Mode(AUDIT, _('Audit'), 0, '', 'usd', None, None, None, None) DEFAULT_MODE_SLUG = AUDIT # Modes that allow a student to pursue a verified certificate @@ -123,7 +135,7 @@ class CourseMode(models.Model): # "honor" to "audit", we still need to have the shoppingcart # use "honor" DEFAULT_SHOPPINGCART_MODE_SLUG = HONOR - DEFAULT_SHOPPINGCART_MODE = Mode(HONOR, _('Honor'), 0, '', 'usd', None, None, None) + DEFAULT_SHOPPINGCART_MODE = Mode(HONOR, _('Honor'), 0, '', 'usd', None, None, None, None) class Meta(object): unique_together = ('course_id', 'mode_slug', 'currency') @@ -625,7 +637,8 @@ class CourseMode(models.Model): self.currency, self.expiration_datetime, self.description, - self.sku + self.sku, + self.bulk_sku ) def __unicode__(self): diff --git a/common/djangoapps/course_modes/tests/test_models.py b/common/djangoapps/course_modes/tests/test_models.py index c0bc615..f992e54 100644 --- a/common/djangoapps/course_modes/tests/test_models.py +++ b/common/djangoapps/course_modes/tests/test_models.py @@ -77,7 +77,7 @@ class CourseModeModelTest(TestCase): self.create_mode('verified', 'Verified Certificate', 10) modes = CourseMode.modes_for_course(self.course_key) - mode = Mode(u'verified', u'Verified Certificate', 10, '', 'usd', None, None, None) + mode = Mode(u'verified', u'Verified Certificate', 10, '', 'usd', None, None, None, None) self.assertEqual([mode], modes) modes_dict = CourseMode.modes_for_course_dict(self.course_key) @@ -89,8 +89,8 @@ class CourseModeModelTest(TestCase): """ Finding the modes when there's multiple modes """ - mode1 = Mode(u'honor', u'Honor Code Certificate', 0, '', 'usd', None, None, None) - mode2 = Mode(u'verified', u'Verified Certificate', 10, '', 'usd', None, None, None) + mode1 = Mode(u'honor', u'Honor Code Certificate', 0, '', 'usd', None, None, None, None) + mode2 = Mode(u'verified', u'Verified Certificate', 10, '', 'usd', None, None, None, None) set_modes = [mode1, mode2] for mode in set_modes: self.create_mode(mode.slug, mode.name, mode.min_price, mode.suggested_prices) @@ -109,9 +109,9 @@ class CourseModeModelTest(TestCase): self.assertEqual(0, CourseMode.min_course_price_for_currency(self.course_key, 'usd')) # create some modes - mode1 = Mode(u'honor', u'Honor Code Certificate', 10, '', 'usd', None, None, None) - mode2 = Mode(u'verified', u'Verified Certificate', 20, '', 'usd', None, None, None) - mode3 = Mode(u'honor', u'Honor Code Certificate', 80, '', 'cny', None, None, None) + mode1 = Mode(u'honor', u'Honor Code Certificate', 10, '', 'usd', None, None, None, None) + mode2 = Mode(u'verified', u'Verified Certificate', 20, '', 'usd', None, None, None, None) + mode3 = Mode(u'honor', u'Honor Code Certificate', 80, '', 'cny', None, None, None, None) set_modes = [mode1, mode2, mode3] for mode in set_modes: self.create_mode(mode.slug, mode.name, mode.min_price, mode.suggested_prices, mode.currency) @@ -126,7 +126,7 @@ class CourseModeModelTest(TestCase): modes = CourseMode.modes_for_course(self.course_key) self.assertEqual([CourseMode.DEFAULT_MODE], modes) - mode1 = Mode(u'honor', u'Honor Code Certificate', 0, '', 'usd', None, None, None) + mode1 = Mode(u'honor', u'Honor Code Certificate', 0, '', 'usd', None, None, None, None) self.create_mode(mode1.slug, mode1.name, mode1.min_price, mode1.suggested_prices) modes = CourseMode.modes_for_course(self.course_key) self.assertEqual([mode1], modes) @@ -134,7 +134,17 @@ class CourseModeModelTest(TestCase): expiration_datetime = datetime.now(pytz.UTC) + timedelta(days=1) expired_mode.expiration_datetime = expiration_datetime expired_mode.save() - expired_mode_value = Mode(u'verified', u'Verified Certificate', 10, '', 'usd', expiration_datetime, None, None) + expired_mode_value = Mode( + u'verified', + u'Verified Certificate', + 10, + '', + 'usd', + expiration_datetime, + None, + None, + None + ) modes = CourseMode.modes_for_course(self.course_key) self.assertEqual([expired_mode_value, mode1], modes) diff --git a/common/djangoapps/course_modes/tests/test_views.py b/common/djangoapps/course_modes/tests/test_views.py index e2de9d6..2097cbb 100644 --- a/common/djangoapps/course_modes/tests/test_views.py +++ b/common/djangoapps/course_modes/tests/test_views.py @@ -99,7 +99,7 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase): # Create the course modes prof_course = CourseFactory.create() CourseModeFactory(mode_slug=CourseMode.NO_ID_PROFESSIONAL_MODE, course_id=prof_course.id, - min_price=100, sku='TEST') + min_price=100, sku='TEST', bulk_sku="BULKTEST") ecomm_test_utils.update_commerce_config(enabled=True) # Enroll the user in the test course CourseEnrollmentFactory( @@ -302,7 +302,7 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase): self.assertEquals(response.status_code, 200) - expected_mode = [Mode(u'honor', u'Honor Code Certificate', 0, '', 'usd', None, None, None)] + expected_mode = [Mode(u'honor', u'Honor Code Certificate', 0, '', 'usd', None, None, None, None)] course_mode = CourseMode.modes_for_course(self.course.id) self.assertEquals(course_mode, expected_mode) @@ -326,7 +326,19 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase): self.assertEquals(response.status_code, 200) - expected_mode = [Mode(mode_slug, mode_display_name, min_price, suggested_prices, currency, None, None, None)] + expected_mode = [ + Mode( + mode_slug, + mode_display_name, + min_price, + suggested_prices, + currency, + None, + None, + None, + None + ) + ] course_mode = CourseMode.modes_for_course(self.course.id) self.assertEquals(course_mode, expected_mode) @@ -349,8 +361,8 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase): url = reverse('create_mode', args=[unicode(self.course.id)]) self.client.get(url, parameters) - honor_mode = Mode(u'honor', u'Honor Code Certificate', 0, '', 'usd', None, None, None) - verified_mode = Mode(u'verified', u'Verified Certificate', 10, '10,20', 'usd', None, None, None) + honor_mode = Mode(u'honor', u'Honor Code Certificate', 0, '', 'usd', None, None, None, None) + verified_mode = Mode(u'verified', u'Verified Certificate', 10, '10,20', 'usd', None, None, None, None) expected_modes = [honor_mode, verified_mode] course_modes = CourseMode.modes_for_course(self.course.id) diff --git a/common/djangoapps/course_modes/views.py b/common/djangoapps/course_modes/views.py index e81d67b..2bf337e 100644 --- a/common/djangoapps/course_modes/views.py +++ b/common/djangoapps/course_modes/views.py @@ -161,6 +161,7 @@ class ChooseModeView(View): context["use_ecommerce_payment_flow"] = ecommerce_service.is_enabled(request.user) context["ecommerce_payment_page"] = ecommerce_service.payment_page_url() context["sku"] = verified_mode.sku + context["bulk_sku"] = verified_mode.bulk_sku return render_to_response("course_modes/choose.html", context) diff --git a/common/djangoapps/enrollment/api.py b/common/djangoapps/enrollment/api.py index 2e352a7..a683398 100644 --- a/common/djangoapps/enrollment/api.py +++ b/common/djangoapps/enrollment/api.py @@ -52,7 +52,8 @@ def get_enrollments(user_id): "currency": "usd", "expiration_datetime": null, "description": null, - "sku": null + "sku": null, + "bulk_sku": null } ], "invite_only": False @@ -78,7 +79,8 @@ def get_enrollments(user_id): "currency": "usd", "expiration_datetime": null, "description": null, - "sku": null + "sku": null, + "bulk_sku": null } ], "invite_only": True @@ -124,7 +126,8 @@ def get_enrollment(user_id, course_id): "currency": "usd", "expiration_datetime": null, "description": null, - "sku": null + "sku": null, + "bulk_sku": null } ], "invite_only": False @@ -175,7 +178,8 @@ def add_enrollment(user_id, course_id, mode=None, is_active=True): "currency": "usd", "expiration_datetime": null, "description": null, - "sku": null + "sku": null, + "bulk_sku": null } ], "invite_only": False @@ -227,7 +231,8 @@ def update_enrollment(user_id, course_id, mode=None, is_active=None, enrollment_ "currency": "usd", "expiration_datetime": null, "description": null, - "sku": null + "sku": null, + "bulk_sku": null } ], "invite_only": False @@ -280,7 +285,8 @@ def get_course_enrollment_details(course_id, include_expired=False): "currency": "usd", "expiration_datetime": null, "description": null, - "sku": null + "sku": null, + "bulk_sku": null } ], "invite_only": False diff --git a/common/djangoapps/enrollment/serializers.py b/common/djangoapps/enrollment/serializers.py index 0047a06..1e894f2 100644 --- a/common/djangoapps/enrollment/serializers.py +++ b/common/djangoapps/enrollment/serializers.py @@ -98,3 +98,4 @@ class ModeSerializer(serializers.Serializer): expiration_datetime = serializers.DateTimeField() description = serializers.CharField() sku = serializers.CharField() + bulk_sku = serializers.CharField() diff --git a/common/djangoapps/enrollment/tests/test_views.py b/common/djangoapps/enrollment/tests/test_views.py index 312c3de..66a1be6 100644 --- a/common/djangoapps/enrollment/tests/test_views.py +++ b/common/djangoapps/enrollment/tests/test_views.py @@ -400,6 +400,7 @@ class EnrollmentTest(EnrollmentTestMixin, ModuleStoreTestCase, APITestCase): mode_slug=CourseMode.HONOR, mode_display_name=CourseMode.HONOR, sku='123', + bulk_sku="BULK123" ) resp = self.client.get( reverse('courseenrollmentdetails', kwargs={"course_id": unicode(self.course.id)}) @@ -411,6 +412,7 @@ class EnrollmentTest(EnrollmentTestMixin, ModuleStoreTestCase, APITestCase): mode = data['course_modes'][0] self.assertEqual(mode['slug'], CourseMode.HONOR) self.assertEqual(mode['sku'], '123') + self.assertEqual(mode['bulk_sku'], 'BULK123') self.assertEqual(mode['name'], CourseMode.HONOR) def test_get_course_details_with_credit_course(self): diff --git a/common/djangoapps/student/views.py b/common/djangoapps/student/views.py index 5c35fe0..eb75876 100644 --- a/common/djangoapps/student/views.py +++ b/common/djangoapps/student/views.py @@ -504,6 +504,7 @@ def complete_course_mode_info(course_id, enrollment, modes=None): if CourseMode.VERIFIED in modes and enrollment.mode in CourseMode.UPSELL_TO_VERIFIED_MODES: mode_info['show_upsell'] = True mode_info['verified_sku'] = modes['verified'].sku + mode_info['verified_bulk_sku'] = modes['verified'].bulk_sku # if there is an expiration date, find out how long from now it is if modes['verified'].expiration_datetime: today = datetime.datetime.now(UTC).date() diff --git a/lms/djangoapps/commerce/api/v0/tests/test_views.py b/lms/djangoapps/commerce/api/v0/tests/test_views.py index 26a161c..2ec8039 100644 --- a/lms/djangoapps/commerce/api/v0/tests/test_views.py +++ b/lms/djangoapps/commerce/api/v0/tests/test_views.py @@ -84,11 +84,13 @@ class BasketsViewTests(EnrollmentEventTestMixin, UserMixin, ModuleStoreTestCase) # TODO Verify this is the best method to create CourseMode objects. # TODO Find/create constants for the modes. for mode in [CourseMode.HONOR, CourseMode.VERIFIED, CourseMode.AUDIT]: + sku_string = uuid4().hex.decode('ascii') CourseModeFactory.create( course_id=self.course.id, mode_slug=mode, mode_display_name=mode, - sku=uuid4().hex.decode('ascii') + sku=sku_string, + bulk_sku='BULK-{}'.format(sku_string) ) # Ignore events fired from UserFactory creation @@ -268,8 +270,9 @@ class BasketsViewTests(EnrollmentEventTestMixin, UserMixin, ModuleStoreTestCase) CourseMode.objects.filter(course_id=self.course.id).delete() mode = CourseMode.NO_ID_PROFESSIONAL_MODE + sku_string = uuid4().hex.decode('ascii') CourseModeFactory.create(course_id=self.course.id, mode_slug=mode, mode_display_name=mode, - sku=uuid4().hex.decode('ascii')) + sku=sku_string, bulk_sku='BULK-{}'.format(sku_string)) with mock_create_basket(expect_called=False): response = self._post_to_view() diff --git a/lms/djangoapps/commerce/api/v1/models.py b/lms/djangoapps/commerce/api/v1/models.py index 691af83..9d7c0f5 100644 --- a/lms/djangoapps/commerce/api/v1/models.py +++ b/lms/djangoapps/commerce/api/v1/models.py @@ -87,6 +87,7 @@ class Course(object): merged_mode.min_price = posted_mode.min_price merged_mode.currency = posted_mode.currency merged_mode.sku = posted_mode.sku + merged_mode.bulk_sku = posted_mode.bulk_sku merged_mode.expiration_datetime = posted_mode.expiration_datetime merged_mode.save() diff --git a/lms/djangoapps/commerce/api/v1/serializers.py b/lms/djangoapps/commerce/api/v1/serializers.py index c3680ff..a114160 100644 --- a/lms/djangoapps/commerce/api/v1/serializers.py +++ b/lms/djangoapps/commerce/api/v1/serializers.py @@ -33,7 +33,7 @@ class CourseModeSerializer(serializers.ModelSerializer): class Meta(object): model = CourseMode - fields = ('name', 'currency', 'price', 'sku', 'expires') + fields = ('name', 'currency', 'price', 'sku', 'bulk_sku', 'expires') def validate_course_id(course_id): diff --git a/lms/djangoapps/commerce/api/v1/tests/test_views.py b/lms/djangoapps/commerce/api/v1/tests/test_views.py index 8ea4e10..41efd05 100644 --- a/lms/djangoapps/commerce/api/v1/tests/test_views.py +++ b/lms/djangoapps/commerce/api/v1/tests/test_views.py @@ -37,8 +37,14 @@ class CourseApiViewTestMixin(object): def setUp(self): super(CourseApiViewTestMixin, self).setUp() self.course = CourseFactory.create() - self.course_mode = CourseMode.objects.create(course_id=self.course.id, mode_slug=u'verified', min_price=100, - currency=u'USD', sku=u'ABC123') + self.course_mode = CourseMode.objects.create( + course_id=self.course.id, + mode_slug=u'verified', + min_price=100, + currency=u'USD', + sku=u'ABC123', + bulk_sku=u'BULK-ABC123' + ) @classmethod def _serialize_datetime(cls, dt): # pylint: disable=invalid-name @@ -58,6 +64,7 @@ class CourseApiViewTestMixin(object): u'currency': course_mode.currency.lower(), u'price': course_mode.min_price, u'sku': course_mode.sku, + u'bulk_sku': course_mode.bulk_sku, u'expires': cls._serialize_datetime(course_mode.expiration_datetime), } @@ -147,6 +154,7 @@ class CourseRetrieveUpdateViewTests(CourseApiViewTestMixin, ModuleStoreTestCase) min_price=200, currency=u'USD', sku=u'ABC123', + bulk_sku=u'BULK-ABC123', expiration_datetime=mode_expiration ) expected = self._serialize_course(self.course, [expected_course_mode], verification_deadline) @@ -217,6 +225,7 @@ class CourseRetrieveUpdateViewTests(CourseApiViewTestMixin, ModuleStoreTestCase) min_price=200, currency=u'USD', sku=u'ABC123', + bulk_sku=u'BULK-ABC123', expiration_datetime=None ) updated_data = self._serialize_course(self.course, [verified_mode], None) @@ -251,7 +260,13 @@ class CourseRetrieveUpdateViewTests(CourseApiViewTestMixin, ModuleStoreTestCase) """ Verify that data submitted via PUT overwrites/deletes modes that are not included in the body of the request. """ course_id = unicode(self.course.id) - expected_course_mode = CourseMode(mode_slug=u'credit', min_price=500, currency=u'USD', sku=u'ABC123') + expected_course_mode = CourseMode( + mode_slug=u'credit', + min_price=500, + currency=u'USD', + sku=u'ABC123', + bulk_sku=u'BULK-ABC123' + ) expected = self._serialize_course(self.course, [expected_course_mode]) path = reverse('commerce_api:v1:courses:retrieve_update', args=[course_id]) response = self.client.put(path, json.dumps(expected), content_type=JSON_CONTENT_TYPE) @@ -276,6 +291,7 @@ class CourseRetrieveUpdateViewTests(CourseApiViewTestMixin, ModuleStoreTestCase) min_price=500, currency=u'USD', sku=u'ABC123', + bulk_sku=u'BULK-ABC123', expiration_datetime=expiration_datetime ) ) @@ -290,8 +306,22 @@ class CourseRetrieveUpdateViewTests(CourseApiViewTestMixin, ModuleStoreTestCase) def assert_can_create_course(self, **request_kwargs): """ Verify a course can be created by the view. """ course = CourseFactory.create() - expected_modes = [CourseMode(mode_slug=u'verified', min_price=150, currency=u'USD', sku=u'ABC123'), - CourseMode(mode_slug=u'honor', min_price=0, currency=u'USD', sku=u'DEADBEEF')] + expected_modes = [ + CourseMode( + mode_slug=u'verified', + min_price=150, + currency=u'USD', + sku=u'ABC123', + bulk_sku=u'BULK-ABC123' + ), + CourseMode( + mode_slug=u'honor', + min_price=0, + currency=u'USD', + sku=u'DEADBEEF', + bulk_sku=u'BULK-DEADBEEF' + ) + ] expected = self._serialize_course(course, expected_modes) path = reverse('commerce_api:v1:courses:retrieve_update', args=[unicode(course.id)]) @@ -331,7 +361,8 @@ class CourseRetrieveUpdateViewTests(CourseApiViewTestMixin, ModuleStoreTestCase) CourseMode( mode_slug=CourseMode.DEFAULT_MODE_SLUG, min_price=150, currency=u'USD', - sku=u'ABC123' + sku=u'ABC123', + bulk_sku=u'BULK-ABC123' ) ] diff --git a/lms/djangoapps/commerce/tests/test_utils.py b/lms/djangoapps/commerce/tests/test_utils.py index ae979a3..f2c405b 100644 --- a/lms/djangoapps/commerce/tests/test_utils.py +++ b/lms/djangoapps/commerce/tests/test_utils.py @@ -54,10 +54,10 @@ class EcommerceServiceTests(TestCase): @patch('openedx.core.djangoapps.theming.helpers.is_request_in_themed_site') def test_is_enabled_for_microsites(self, is_microsite): - """Verify that is_enabled() returns False if used for a microsite.""" + """Verify that is_enabled() returns True if used for a microsite.""" is_microsite.return_value = True - is_not_enabled = EcommerceService().is_enabled(self.user) - self.assertFalse(is_not_enabled) + is_enabled = EcommerceService().is_enabled(self.user) + self.assertTrue(is_enabled) @override_settings(ECOMMERCE_PUBLIC_URL_ROOT='http://ecommerce_url') def test_payment_page_url(self): diff --git a/lms/djangoapps/commerce/utils.py b/lms/djangoapps/commerce/utils.py index a4e775c..0591990 100644 --- a/lms/djangoapps/commerce/utils.py +++ b/lms/djangoapps/commerce/utils.py @@ -45,9 +45,10 @@ class EcommerceService(object): self.config = CommerceConfiguration.current() def is_enabled(self, user): - """ Check if the user is activated, if the service is enabled and that the site is not a microsite. """ - return (user.is_active and self.config.checkout_on_ecommerce_service and not - helpers.is_request_in_themed_site()) + """ + Determines the availability of the Ecommerce service based on user activation and service configuration. + """ + return user.is_active and self.config.checkout_on_ecommerce_service def payment_page_url(self): """ Return the URL for the checkout page. diff --git a/lms/djangoapps/commerce/views.py b/lms/djangoapps/commerce/views.py index 75750d5..291bff1 100644 --- a/lms/djangoapps/commerce/views.py +++ b/lms/djangoapps/commerce/views.py @@ -10,6 +10,7 @@ from microsite_configuration import microsite from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification from shoppingcart.processors.CyberSource2 import is_user_payment_error from django.utils.translation import ugettext as _ +from openedx.core.djangoapps.theming.helpers import is_request_in_themed_site log = logging.getLogger(__name__) @@ -75,5 +76,6 @@ def checkout_receipt(request): 'payment_support_email': payment_support_email, 'username': request.user.username, 'nav_hidden': True, + 'is_request_in_themed_site': is_request_in_themed_site() } return render_to_response('commerce/checkout_receipt.html', context) diff --git a/lms/djangoapps/courseware/views/views.py b/lms/djangoapps/courseware/views/views.py index f0a797d..5ea313a 100644 --- a/lms/djangoapps/courseware/views/views.py +++ b/lms/djangoapps/courseware/views/views.py @@ -512,7 +512,8 @@ def course_about(request, course_id): # professional or no id professional, we construct links for the enrollment # button to add the course to the ecommerce basket. ecommerce_checkout_link = '' - professional_mode = '' + ecommerce_bulk_checkout_link = '' + professional_mode = None ecomm_service = EcommerceService() if ecomm_service.is_enabled(request.user) and ( CourseMode.PROFESSIONAL in modes or CourseMode.NO_ID_PROFESSIONAL_MODE in modes @@ -520,7 +521,8 @@ def course_about(request, course_id): professional_mode = modes.get(CourseMode.PROFESSIONAL, '') or \ modes.get(CourseMode.NO_ID_PROFESSIONAL_MODE, '') ecommerce_checkout_link = ecomm_service.checkout_page_url(professional_mode.sku) - + if professional_mode.bulk_sku: + ecommerce_bulk_checkout_link = ecomm_service.checkout_page_url(professional_mode.bulk_sku) course_price = get_cosmetic_display_price(course, registration_price) can_add_course_to_cart = _is_shopping_cart_enabled and registration_price @@ -555,6 +557,7 @@ def course_about(request, course_id): 'in_cart': in_cart, 'ecommerce_checkout': ecomm_service.is_enabled(request.user), 'ecommerce_checkout_link': ecommerce_checkout_link, + 'ecommerce_bulk_checkout_link': ecommerce_bulk_checkout_link, 'professional_mode': professional_mode, 'reg_then_add_to_cart_link': reg_then_add_to_cart_link, 'show_courseware_link': show_courseware_link, diff --git a/lms/static/js/commerce/views/receipt_view.js b/lms/static/js/commerce/views/receipt_view.js index 0b8adbc..a265632 100644 --- a/lms/static/js/commerce/views/receipt_view.js +++ b/lms/static/js/commerce/views/receipt_view.js @@ -31,7 +31,8 @@ var edx = edx || {}; var templateHtml = $("#receipt-tpl").html(), context = { platformName: this.$el.data('platform-name'), - verified: this.$el.data('verified').toLowerCase() === 'true' + verified: this.$el.data('verified').toLowerCase() === 'true', + is_request_in_themed_site: this.$el.data('is-request-in-themed-site').toLowerCase() === 'true' }, providerId; diff --git a/lms/templates/commerce/checkout_receipt.html b/lms/templates/commerce/checkout_receipt.html index fe8a57f..a743c97 100644 --- a/lms/templates/commerce/checkout_receipt.html +++ b/lms/templates/commerce/checkout_receipt.html @@ -52,7 +52,8 @@ from django.utils.translation import ugettext as _ <div class="container"> <section class="wrapper carousel"> <div id="receipt-container" class="pay-and-verify hidden" data-is-payment-complete='${is_payment_complete}' - data-platform-name='${platform_name}' data-verified='${verified}' data-username='${username}'> + data-platform-name='${platform_name}' data-verified='${verified}' data-username='${username}' + data-is-request-in-themed-site='${is_request_in_themed_site}'> <h1>${_("Loading Order Data...")}</h1> <span>${ _("Please wait while we retrieve your order details.") }</span> </div> diff --git a/lms/templates/commerce/receipt.underscore b/lms/templates/commerce/receipt.underscore index 70d3e5f..6b9f06d 100644 --- a/lms/templates/commerce/receipt.underscore +++ b/lms/templates/commerce/receipt.underscore @@ -86,7 +86,7 @@ <% } %> <nav class="nav-wizard is-ready"> - <% if ( verified ) { %> + <% if ( verified || is_request_in_themed_site) { %> <a class="next action-primary right" href="/dashboard"><%- gettext( "Go to Dashboard" ) %></a> <% } else { %> <a id="verify_later_button" class="next action-secondary verify-later nav-link" href="/dashboard" data-tooltip="<%- _.sprintf( gettext( "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from %(platformName)s to verify your identity." ), { platformName: platformName } ) %>">