Commit fc1653aa by PaulWattenberger Committed by GitHub

Merge pull request #890 from edx/pwattenberger/sailthru-3

Add missing basket_addition call.  Handle call to post_checkout with no user=
parents 4a0f47d8 89865d33
...@@ -200,7 +200,7 @@ class CouponViewSet(EdxOrderPlacementMixin, viewsets.ModelViewSet): ...@@ -200,7 +200,7 @@ class CouponViewSet(EdxOrderPlacementMixin, viewsets.ModelViewSet):
# Create an order now since payment is handled out of band via an invoice. # Create an order now since payment is handled out of band via an invoice.
response_data = self.create_order_for_invoice( response_data = self.create_order_for_invoice(
basket, coupon_id=coupon_product.id, client=client, invoice_data=invoice_data basket, coupon_id=coupon_product.id, client=client, invoice_data=invoice_data, request=request
) )
return Response(response_data, status=status.HTTP_200_OK) return Response(response_data, status=status.HTTP_200_OK)
...@@ -284,7 +284,7 @@ class CouponViewSet(EdxOrderPlacementMixin, viewsets.ModelViewSet): ...@@ -284,7 +284,7 @@ class CouponViewSet(EdxOrderPlacementMixin, viewsets.ModelViewSet):
for category in categories: for category in categories:
ProductCategory.objects.get_or_create(product=coupon, category=category) ProductCategory.objects.get_or_create(product=coupon, category=category)
def create_order_for_invoice(self, basket, coupon_id, client, invoice_data=None): def create_order_for_invoice(self, basket, coupon_id, client, invoice_data=None, request=None):
"""Creates an order from the basket and invokes the invoice payment processor.""" """Creates an order from the basket and invokes the invoice payment processor."""
order_metadata = data_api.get_order_metadata(basket) order_metadata = data_api.get_order_metadata(basket)
...@@ -304,7 +304,8 @@ class CouponViewSet(EdxOrderPlacementMixin, viewsets.ModelViewSet): ...@@ -304,7 +304,8 @@ class CouponViewSet(EdxOrderPlacementMixin, viewsets.ModelViewSet):
shipping_method=order_metadata[AC.KEYS.SHIPPING_METHOD], shipping_method=order_metadata[AC.KEYS.SHIPPING_METHOD],
shipping_charge=order_metadata[AC.KEYS.SHIPPING_CHARGE], shipping_charge=order_metadata[AC.KEYS.SHIPPING_CHARGE],
billing_address=None, billing_address=None,
order_total=order_metadata[AC.KEYS.ORDER_TOTAL] order_total=order_metadata[AC.KEYS.ORDER_TOTAL],
request=request
) )
# Invoice payment processor invocation. # Invoice payment processor invocation.
......
...@@ -54,7 +54,7 @@ class OrderViewSet(viewsets.ReadOnlyModelViewSet): ...@@ -54,7 +54,7 @@ class OrderViewSet(viewsets.ReadOnlyModelViewSet):
logger.info('Attempting fulfillment of order [%s]...', order.number) logger.info('Attempting fulfillment of order [%s]...', order.number)
post_checkout = get_class('checkout.signals', 'post_checkout') post_checkout = get_class('checkout.signals', 'post_checkout')
post_checkout.send(sender=post_checkout, order=order) post_checkout.send(sender=post_checkout, order=order, request=request)
if order.is_fulfillable: if order.is_fulfillable:
logger.warning('Fulfillment of order [%s] failed!', order.number) logger.warning('Fulfillment of order [%s] failed!', order.number)
......
...@@ -51,6 +51,10 @@ def prepare_basket(request, product, voucher=None): ...@@ -51,6 +51,10 @@ def prepare_basket(request, product, voucher=None):
else: else:
Referral.objects.filter(basket=basket).delete() Referral.objects.filter(basket=basket).delete()
# Call signal handler to notify listeners that something has been added to the basket
basket_addition = get_class('basket.signals', 'basket_addition')
basket_addition.send(sender=basket_addition, product=product, user=request.user, request=request)
return basket return basket
......
...@@ -70,6 +70,7 @@ class EdxOrderPlacementMixin(OrderPlacementMixin): ...@@ -70,6 +70,7 @@ class EdxOrderPlacementMixin(OrderPlacementMixin):
shipping_charge, shipping_charge,
billing_address, billing_address,
order_total, order_total,
request=None,
**kwargs): **kwargs):
""" """
Place an order and mark the corresponding basket as submitted. Place an order and mark the corresponding basket as submitted.
...@@ -93,9 +94,9 @@ class EdxOrderPlacementMixin(OrderPlacementMixin): ...@@ -93,9 +94,9 @@ class EdxOrderPlacementMixin(OrderPlacementMixin):
basket.submit() basket.submit()
return self.handle_successful_order(order) return self.handle_successful_order(order, request)
def handle_successful_order(self, order): def handle_successful_order(self, order, request=None): # pylint: disable=arguments-differ
"""Send a signal so that receivers can perform relevant tasks (e.g., fulfill the order).""" """Send a signal so that receivers can perform relevant tasks (e.g., fulfill the order)."""
audit_log( audit_log(
'order_placed', 'order_placed',
...@@ -114,11 +115,11 @@ class EdxOrderPlacementMixin(OrderPlacementMixin): ...@@ -114,11 +115,11 @@ class EdxOrderPlacementMixin(OrderPlacementMixin):
# See http://celery.readthedocs.org/en/latest/userguide/tasks.html#database-transactions. # See http://celery.readthedocs.org/en/latest/userguide/tasks.html#database-transactions.
fulfill_order.delay(order.number, site_code=order.site.siteconfiguration.partner.short_code) fulfill_order.delay(order.number, site_code=order.site.siteconfiguration.partner.short_code)
else: else:
post_checkout.send(sender=self, order=order) post_checkout.send(sender=self, order=order, request=request)
return order return order
def place_free_order(self, basket): def place_free_order(self, basket, request=None):
"""Fulfill a free order. """Fulfill a free order.
Arguments: Arguments:
...@@ -155,6 +156,7 @@ class EdxOrderPlacementMixin(OrderPlacementMixin): ...@@ -155,6 +156,7 @@ class EdxOrderPlacementMixin(OrderPlacementMixin):
shipping_charge=order_metadata[AC.KEYS.SHIPPING_CHARGE], shipping_charge=order_metadata[AC.KEYS.SHIPPING_CHARGE],
billing_address=None, billing_address=None,
order_total=order_metadata[AC.KEYS.ORDER_TOTAL], order_total=order_metadata[AC.KEYS.ORDER_TOTAL],
request=request
) )
return order return order
......
...@@ -162,7 +162,8 @@ class CybersourceNotifyView(EdxOrderPlacementMixin, View): ...@@ -162,7 +162,8 @@ class CybersourceNotifyView(EdxOrderPlacementMixin, View):
shipping_method, shipping_method,
shipping_charge, shipping_charge,
billing_address, billing_address,
order_total order_total,
request=request
) )
return HttpResponse() return HttpResponse()
...@@ -255,7 +256,8 @@ class PaypalPaymentExecutionView(EdxOrderPlacementMixin, View): ...@@ -255,7 +256,8 @@ class PaypalPaymentExecutionView(EdxOrderPlacementMixin, View):
shipping_method=shipping_method, shipping_method=shipping_method,
shipping_charge=shipping_charge, shipping_charge=shipping_charge,
billing_address=None, billing_address=None,
order_total=order_total order_total=order_total,
request=request
) )
return redirect(receipt_url) return redirect(receipt_url)
......
...@@ -17,7 +17,8 @@ basket_addition = get_class('basket.signals', 'basket_addition') ...@@ -17,7 +17,8 @@ basket_addition = get_class('basket.signals', 'basket_addition')
@receiver(post_checkout) @receiver(post_checkout)
@silence_exceptions("Failed to call Sailthru upon order completion.") @silence_exceptions("Failed to call Sailthru upon order completion.")
def process_checkout_complete(sender, order=None, request=None, user=None, **kwargs): # pylint: disable=unused-argument def process_checkout_complete(sender, order=None, user=None, request=None, # pylint: disable=unused-argument
response=None, **kwargs): # pylint: disable=unused-argument
"""Tell Sailthru when payment done. """Tell Sailthru when payment done.
Arguments: Arguments:
...@@ -27,6 +28,10 @@ def process_checkout_complete(sender, order=None, request=None, user=None, **kwa ...@@ -27,6 +28,10 @@ def process_checkout_complete(sender, order=None, request=None, user=None, **kwa
if not waffle.switch_is_active('sailthru_enable'): if not waffle.switch_is_active('sailthru_enable'):
return return
message_id = None
if request:
message_id = request.COOKIES.get('sailthru_bid')
# loop through lines in order # loop through lines in order
# If multi product orders become common it may be worthwhile to pass an array of # If multi product orders become common it may be worthwhile to pass an array of
# orders to the worker in one call to save overhead, however, that would be difficult # orders to the worker in one call to save overhead, however, that would be difficult
...@@ -45,15 +50,15 @@ def process_checkout_complete(sender, order=None, request=None, user=None, **kwa ...@@ -45,15 +50,15 @@ def process_checkout_complete(sender, order=None, request=None, user=None, **kwa
course_url = _build_course_url(course_id) course_url = _build_course_url(course_id)
# pass event to ecommerce_worker.sailthru.v1.tasks to handle asynchronously # pass event to ecommerce_worker.sailthru.v1.tasks to handle asynchronously
update_course_enrollment.delay(user.email, course_url, False, mode_for_seat(product), update_course_enrollment.delay(order.user.email, course_url, False, mode_for_seat(product),
unit_cost=price, course_id=course_id, currency=order.currency, unit_cost=price, course_id=course_id, currency=order.currency,
site_code=request.site.siteconfiguration.partner.short_code, site_code=order.site.siteconfiguration.partner.short_code,
message_id=request.COOKIES.get('sailthru_bid')) message_id=message_id)
@receiver(basket_addition) @receiver(basket_addition)
@silence_exceptions("Failed to call Sailthru upon basket addition.") @silence_exceptions("Failed to call Sailthru upon basket addition.")
def process_basket_addition(sender, product=None, request=None, user=None, **kwargs): # pylint: disable=unused-argument def process_basket_addition(sender, product=None, user=None, request=None, **kwargs): # pylint: disable=unused-argument
"""Tell Sailthru when payment started. """Tell Sailthru when payment started.
Arguments: Arguments:
......
...@@ -56,9 +56,7 @@ class SailthruTests(CourseCatalogTestMixin, TestCase): ...@@ -56,9 +56,7 @@ class SailthruTests(CourseCatalogTestMixin, TestCase):
""" """
seat, order = self._create_order(99) seat, order = self._create_order(99)
process_checkout_complete(None, request=self.request, process_checkout_complete(None, order=order, request=self.request)
user=self.user,
order=order)
self.assertTrue(mock_update_course_enrollment.called) self.assertTrue(mock_update_course_enrollment.called)
mock_update_course_enrollment.assert_called_with(TEST_EMAIL, mock_update_course_enrollment.assert_called_with(TEST_EMAIL,
self.course_url, self.course_url,
...@@ -71,6 +69,25 @@ class SailthruTests(CourseCatalogTestMixin, TestCase): ...@@ -71,6 +69,25 @@ class SailthruTests(CourseCatalogTestMixin, TestCase):
unit_cost=order.total_excl_tax) unit_cost=order.total_excl_tax)
@patch('ecommerce_worker.sailthru.v1.tasks.update_course_enrollment.delay') @patch('ecommerce_worker.sailthru.v1.tasks.update_course_enrollment.delay')
def test_process_checkout_complete_no_request(self, mock_update_course_enrollment):
"""
Test that the process_checkout signal handler properly handles null request
"""
seat, order = self._create_order(99)
process_checkout_complete(None, order=order)
self.assertTrue(mock_update_course_enrollment.called)
mock_update_course_enrollment.assert_called_with(TEST_EMAIL,
self.course_url,
False,
seat.attr.certificate_type,
course_id=self.course_id,
currency=order.currency,
message_id=None,
site_code='edX',
unit_cost=order.total_excl_tax)
@patch('ecommerce_worker.sailthru.v1.tasks.update_course_enrollment.delay')
def test_process_basket_addition(self, mock_update_course_enrollment): def test_process_basket_addition(self, mock_update_course_enrollment):
""" """
Test that the process_basket_addition signal handler properly calls the task routine Test that the process_basket_addition signal handler properly calls the task routine
......
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