diff --git a/common/djangoapps/course_modes/models.py b/common/djangoapps/course_modes/models.py index f110d09002..810b5ddca2 100644 --- a/common/djangoapps/course_modes/models.py +++ b/common/djangoapps/course_modes/models.py @@ -86,6 +86,11 @@ class CourseMode(models.Model): """ meta attributes of this model """ unique_together = ('course_id', 'mode_slug', 'currency') + def save(self, force_insert=False, force_update=False, using=None): + # Ensure currency is always lowercase. + self.currency = self.currency.lower() + super(CourseMode, self).save(force_insert, force_update, using) + @classmethod def all_modes_for_courses(cls, course_id_list): """Find all modes for a list of course IDs, including expired modes. @@ -308,7 +313,7 @@ class CourseMode(models.Model): """ modes = cls.modes_for_course(course_id) for mode in modes: - if (mode.currency == currency) and (mode.slug == 'verified'): + if (mode.currency.lower() == currency.lower()) and (mode.slug == 'verified'): return mode.min_price return 0 @@ -490,7 +495,7 @@ class CourseMode(models.Model): If there is no mode found, will return the price of DEFAULT_MODE, which is 0 """ modes = cls.modes_for_course(course_id) - return min(mode.min_price for mode in modes if mode.currency == currency) + return min(mode.min_price for mode in modes if mode.currency.lower() == currency.lower()) @classmethod def enrollment_mode_display(cls, mode, verification_status): diff --git a/common/djangoapps/course_modes/tests/test_models.py b/common/djangoapps/course_modes/tests/test_models.py index ac02931725..814291c711 100644 --- a/common/djangoapps/course_modes/tests/test_models.py +++ b/common/djangoapps/course_modes/tests/test_models.py @@ -39,6 +39,15 @@ class CourseModeModelTest(TestCase): currency=currency, ) + def test_save(self): + """ Verify currency is always lowercase. """ + cm, __ = self.create_mode('honor', 'honor', 0, '', 'USD') + self.assertEqual(cm.currency, 'usd') + + cm.currency = 'GHS' + cm.save() + self.assertEqual(cm.currency, 'ghs') + def test_modes_for_course_empty(self): """ If we can't find any modes, we should get back the default mode diff --git a/lms/djangoapps/commerce/api/v1/tests/test_views.py b/lms/djangoapps/commerce/api/v1/tests/test_views.py index 6dc7606258..2e0b0562ab 100644 --- a/lms/djangoapps/commerce/api/v1/tests/test_views.py +++ b/lms/djangoapps/commerce/api/v1/tests/test_views.py @@ -33,7 +33,7 @@ class CourseApiViewTestMixin(object): """ Serialize a CourseMode to a dict. """ return { u'name': course_mode.mode_slug, - u'currency': course_mode.currency, + u'currency': course_mode.currency.lower(), u'price': course_mode.min_price, u'sku': course_mode.sku } diff --git a/lms/djangoapps/shoppingcart/processors/CyberSource2.py b/lms/djangoapps/shoppingcart/processors/CyberSource2.py index 83a063ace5..846f2a039e 100644 --- a/lms/djangoapps/shoppingcart/processors/CyberSource2.py +++ b/lms/djangoapps/shoppingcart/processors/CyberSource2.py @@ -357,7 +357,7 @@ def _payment_accepted(order_id, auth_amount, currency, decision): raise CCProcessorDataException(_("The payment processor accepted an order whose number is not in our system.")) if decision == 'ACCEPT': - if auth_amount == order.total_cost and currency == order.currency: + if auth_amount == order.total_cost and currency.lower() == order.currency.lower(): return { 'accepted': True, 'amt_charged': auth_amount,