Commit 60cc2ed7 by McKenzie Welter Committed by McKenzie Welter

handle stock record errors in ecomm dataloader

parent 2a87747b
...@@ -383,19 +383,39 @@ class EcommerceApiDataLoader(AbstractDataLoader): ...@@ -383,19 +383,39 @@ class EcommerceApiDataLoader(AbstractDataLoader):
defaults=defaults) defaults=defaults)
def update_entitlement(self, body): def update_entitlement(self, body):
"""
Argument:
body (dict): entitlement product data from ecommerce
Returns:
entitlement product sku if no exceptions, else None
"""
attributes = {attribute['name']: attribute['value'] for attribute in body['attribute_values']} attributes = {attribute['name']: attribute['value'] for attribute in body['attribute_values']}
course_uuid = attributes.get('UUID') course_uuid = attributes.get('UUID')
title = body['title']
stock_record = body['stockrecords'][0] if body['stockrecords']:
currency_code = stock_record['price_currency'] stock_record = body['stockrecords'][0]
price = Decimal(stock_record['price_excl_tax']) else:
sku = stock_record['partner_sku'] msg = 'Entitlement product {entitlement} has no stockrecords'.format(entitlement=title)
logger.warning(msg)
return None
try:
currency_code = stock_record['price_currency']
price = Decimal(stock_record['price_excl_tax'])
sku = stock_record['partner_sku']
except (KeyError, ValueError):
msg = 'A necessary stockrecord field is missing or incorrectly set for entitlement {entitlement}'.format(
entitlement=title
)
logger.warning(msg)
return None
try: try:
course = Course.objects.get(uuid=course_uuid) course = Course.objects.get(uuid=course_uuid)
except Course.DoesNotExist: except Course.DoesNotExist:
msg = 'Could not find course {uuid} while loading entitlement {entitlement} with sku {sku}'.format( msg = 'Could not find course {uuid} while loading entitlement {entitlement} with sku {sku}'.format(
uuid=course_uuid, entitlement=body['title'], sku=sku uuid=course_uuid, entitlement=title, sku=sku
) )
logger.warning(msg) logger.warning(msg)
return None return None
...@@ -404,7 +424,7 @@ class EcommerceApiDataLoader(AbstractDataLoader): ...@@ -404,7 +424,7 @@ class EcommerceApiDataLoader(AbstractDataLoader):
currency = Currency.objects.get(code=currency_code) currency = Currency.objects.get(code=currency_code)
except Currency.DoesNotExist: except Currency.DoesNotExist:
msg = 'Could not find currency {code} while loading entitlement {entitlement} with sku {sku}'.format( msg = 'Could not find currency {code} while loading entitlement {entitlement} with sku {sku}'.format(
code=currency_code, entitlement=body['title'], sku=sku code=currency_code, entitlement=title, sku=sku
) )
logger.warning(msg) logger.warning(msg)
return None return None
...@@ -414,7 +434,7 @@ class EcommerceApiDataLoader(AbstractDataLoader): ...@@ -414,7 +434,7 @@ class EcommerceApiDataLoader(AbstractDataLoader):
mode = SeatType.objects.get(slug=mode_name) mode = SeatType.objects.get(slug=mode_name)
except SeatType.DoesNotExist: except SeatType.DoesNotExist:
msg = 'Could not find mode {mode} while loading entitlement {entitlement} with sku {sku}'.format( msg = 'Could not find mode {mode} while loading entitlement {entitlement} with sku {sku}'.format(
mode=mode_name, entitlement=body['title'], sku=sku mode=mode_name, entitlement=title, sku=sku
) )
logger.warning(msg) logger.warning(msg)
return None return None
...@@ -427,7 +447,7 @@ class EcommerceApiDataLoader(AbstractDataLoader): ...@@ -427,7 +447,7 @@ class EcommerceApiDataLoader(AbstractDataLoader):
'expires': self.parse_date(body['expires']) 'expires': self.parse_date(body['expires'])
} }
msg = 'Creating entitlement {entitlement} with sku {sku} for partner {partner}'.format( msg = 'Creating entitlement {entitlement} with sku {sku} for partner {partner}'.format(
entitlement=body['title'], sku=sku, partner=self.partner entitlement=title, sku=sku, partner=self.partner
) )
logger.info(msg) logger.info(msg)
course.entitlements.update_or_create(mode=mode, defaults=defaults) course.entitlements.update_or_create(mode=mode, defaults=defaults)
......
...@@ -364,7 +364,8 @@ class EcommerceApiDataLoaderTests(ApiClientTestMixin, DataLoaderTestMixin, TestC ...@@ -364,7 +364,8 @@ class EcommerceApiDataLoaderTests(ApiClientTestMixin, DataLoaderTestMixin, TestC
) )
return bodies return bodies
def mock_products_api(self, alt_course=None, alt_currency=None, alt_mode=None): def mock_products_api(self, alt_course=None, alt_currency=None, alt_mode=None, has_stockrecord=True,
valid_stockrecord=True):
""" Return a new Course Entitlement to be added by ingest """ """ Return a new Course Entitlement to be added by ingest """
course = CourseFactory() course = CourseFactory()
...@@ -386,15 +387,18 @@ class EcommerceApiDataLoaderTests(ApiClientTestMixin, DataLoaderTestMixin, TestC ...@@ -386,15 +387,18 @@ class EcommerceApiDataLoaderTests(ApiClientTestMixin, DataLoaderTestMixin, TestC
} }
], ],
"is_available_to_buy": True, "is_available_to_buy": True,
"stockrecords": [ "stockrecords": []
{
"partner_sku": "sku132",
"price_currency": alt_currency if alt_currency else "USD",
"price_excl_tax": "10.00",
}
]
} }
] ]
stockrecord = {
"price_currency": alt_currency if alt_currency else "USD",
"price_excl_tax": "10.00",
}
if valid_stockrecord:
stockrecord.update({"partner_sku": "sku132"})
if has_stockrecord:
bodies[0]["stockrecords"].append(stockrecord)
url = '{url}products/'.format(url=self.api_url) url = '{url}products/'.format(url=self.api_url)
responses.add_callback( responses.add_callback(
responses.GET, responses.GET,
...@@ -525,6 +529,26 @@ class EcommerceApiDataLoaderTests(ApiClientTestMixin, DataLoaderTestMixin, TestC ...@@ -525,6 +529,26 @@ class EcommerceApiDataLoaderTests(ApiClientTestMixin, DataLoaderTestMixin, TestC
mock_logger.info.assert_any_call(msg) mock_logger.info.assert_any_call(msg)
@responses.activate @responses.activate
@mock.patch(LOGGER_PATH)
def test_no_stockrecord(self, mock_logger):
self.mock_courses_api()
products = self.mock_products_api(has_stockrecord=False)
self.loader.ingest()
msg = 'Entitlement product {entitlement} has no stockrecords'.format(entitlement=products[0]['title'])
mock_logger.warning.assert_called_with(msg)
@responses.activate
@mock.patch(LOGGER_PATH)
def test_invalid_stockrecord(self, mock_logger):
self.mock_courses_api()
products = self.mock_products_api(valid_stockrecord=False)
self.loader.ingest()
msg = 'A necessary stockrecord field is missing or incorrectly set for entitlement {entitlement}'.format(
entitlement=products[0]['title']
)
mock_logger.warning.assert_called_with(msg)
@responses.activate
@ddt.data( @ddt.data(
('a01354b1-c0de-4a6b-c5de-ab5c6d869e76', None, None), ('a01354b1-c0de-4a6b-c5de-ab5c6d869e76', None, None),
(None, "NRC", None), (None, "NRC", None),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment