From 9934b648b6e007a9f1eca8c067ff7828638fff59 Mon Sep 17 00:00:00 2001
From: George Babey <gbabey@edx.org>
Date: Wed, 10 Jan 2018 11:40:25 -0500
Subject: [PATCH] Add util method for localizing catalog pricing

---
 .../djangoapps/catalog/tests/test_utils.py    | 32 +++++++++++++-
 openedx/core/djangoapps/catalog/utils.py      | 44 +++++++++++++++++++
 requirements/edx/base.txt                     |  3 +-
 3 files changed, 76 insertions(+), 3 deletions(-)

diff --git a/openedx/core/djangoapps/catalog/tests/test_utils.py b/openedx/core/djangoapps/catalog/tests/test_utils.py
index 27be16fd8bb..33028dfb068 100644
--- a/openedx/core/djangoapps/catalog/tests/test_utils.py
+++ b/openedx/core/djangoapps/catalog/tests/test_utils.py
@@ -7,17 +7,24 @@ import mock
 from django.contrib.auth import get_user_model
 from django.core.cache import cache
 from django.test import TestCase, override_settings
+from django.test.client import RequestFactory
 from student.tests.factories import UserFactory
 
 from openedx.core.djangoapps.catalog.cache import PROGRAM_CACHE_KEY_TPL, SITE_PROGRAM_UUIDS_CACHE_KEY_TPL
 from openedx.core.djangoapps.catalog.models import CatalogIntegration
-from openedx.core.djangoapps.catalog.tests.factories import CourseFactory, CourseRunFactory, ProgramFactory, ProgramTypeFactory
+from openedx.core.djangoapps.catalog.tests.factories import (
+    CourseFactory,
+    CourseRunFactory,
+    ProgramFactory,
+    ProgramTypeFactory
+)
 from openedx.core.djangoapps.catalog.tests.mixins import CatalogIntegrationMixin
 from openedx.core.djangoapps.catalog.utils import (
     get_course_runs,
     get_course_runs_for_course,
     get_course_run_details,
     get_currency_data,
+    get_localized_price_text,
     get_program_types,
     get_programs,
     get_programs_with_type
@@ -266,6 +273,27 @@ class TestGetCurrency(CatalogIntegrationMixin, TestCase):
         self.assertEqual(data, currency_data)
 
 
+@mock.patch(UTILS_MODULE + '.get_currency_data')
+class TestGetLocalizedPriceText(TestCase):
+    """
+    Tests covering converting prices to a localized currency
+    """
+    def test_localized_string(self, mock_get_currency_data):
+        currency_data = {
+            "BEL": {"rate": 0.835621, "code": "EUR", "symbol": u"\u20ac"},
+            "GBR": {"rate": 0.737822, "code": "GBP", "symbol": u"\u00a3"},
+            "CAN": {"rate": 2, "code": "CAD", "symbol": "$"},
+        }
+        mock_get_currency_data.return_value = currency_data
+
+        request = RequestFactory().get('/dummy-url')
+        request.session = {
+            'country_code': 'CA'
+        }
+        expected_result = '$20 CAD'
+        self.assertEqual(get_localized_price_text(10, request), expected_result)
+
+
 @skip_unless_lms
 @mock.patch(UTILS_MODULE + '.get_edx_api_data')
 class TestGetCourseRuns(CatalogIntegrationMixin, TestCase):
@@ -278,7 +306,7 @@ class TestGetCourseRuns(CatalogIntegrationMixin, TestCase):
         self.catalog_integration = self.create_catalog_integration(cache_ttl=1)
         self.user = UserFactory(username=self.catalog_integration.service_username)
 
-    def assert_contract(self, call_args):  # pylint: disable=redefined-builtin
+    def assert_contract(self, call_args):
         """
         Verify that API data retrieval utility is used correctly.
         """
diff --git a/openedx/core/djangoapps/catalog/utils.py b/openedx/core/djangoapps/catalog/utils.py
index b1990c12779..1eabbbfd855 100644
--- a/openedx/core/djangoapps/catalog/utils.py
+++ b/openedx/core/djangoapps/catalog/utils.py
@@ -2,6 +2,7 @@
 import copy
 import datetime
 import logging
+import pycountry
 
 from dateutil.parser import parse as datetime_parse
 from django.conf import settings
@@ -144,6 +145,49 @@ def get_currency_data():
         return []
 
 
+def format_price(price, symbol='$', code='USD'):
+    """
+    Format the price to have the appropriate currency and digits..
+
+    :param price: The price amount.
+    :param symbol: The symbol for the price (default: $)
+    :param code: The currency code to be appended to the price (default: USD)
+    :return: A formatted price string, i.e. '$10 USD', '$10.52 USD'.
+    """
+    if int(price) == price:
+        return '{}{} {}'.format(symbol, int(price), code)
+    return '{}{:0.2f} {}'.format(symbol, price, code)
+
+
+def get_localized_price_text(price, request):
+    """
+    Returns the localized converted price as string (ex. '$150 USD')
+
+    If the users location has been added to the request, this will return the given price based on conversion rate
+    from the Catalog service and return a localized string otherwise will return the default price in USD
+    """
+    user_currency = {
+        'symbol': '$',
+        'rate': 1,
+        'code': 'USD'
+    }
+
+    # session.country_code is added via CountryMiddleware in the LMS
+    user_location = getattr(request, 'session', {}).get('country_code')
+
+    # Override default user_currency if location is available
+    if user_location and get_currency_data:
+        currency_data = get_currency_data()
+        user_country = pycountry.countries.get(alpha2=user_location)
+        user_currency = currency_data.get(user_country.alpha3, user_currency)
+
+    return format_price(
+        price=(price * user_currency['rate']),
+        symbol=user_currency['symbol'],
+        code=user_currency['code']
+    )
+
+
 def get_programs_with_type(site, include_hidden=True):
     """
     Return the list of programs. You can filter the types of programs returned by using the optional
diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt
index e0be0419bda..5f2e7969f7f 100644
--- a/requirements/edx/base.txt
+++ b/requirements/edx/base.txt
@@ -54,7 +54,7 @@ git+https://github.com/cpennington/pylint-django@fix-field-inference-during-monk
 enum34==1.1.6
 edx-django-oauth2-provider==1.2.5
 edx-django-sites-extensions==2.3.0
-edx-enterprise==0.61.3
+edx-enterprise==0.61.4
 edx-oauth2-provider==1.2.2
 edx-organizations==0.4.9
 edx-rest-api-client==1.7.1
@@ -86,6 +86,7 @@ piexif==1.0.2
 Pillow==3.4
 polib==1.0.3
 psutil==1.2.1
+pycountry==1.20
 pycryptodomex==3.4.7
 pygments==2.2.0
 pygraphviz==1.1
-- 
GitLab