Add tracking for refunds.
This commit is contained in:
@@ -438,15 +438,23 @@ class Order(models.Model):
|
||||
csv_file, courses_info = self.generate_registration_codes_csv(orderitems, site_name)
|
||||
|
||||
self.send_confirmation_emails(orderitems, self.order_type == OrderTypes.BUSINESS, csv_file, site_name, courses_info)
|
||||
self._emit_purchase_event(orderitems)
|
||||
self._emit_order_event('Completed Order', orderitems)
|
||||
|
||||
def _emit_purchase_event(self, orderitems):
|
||||
def refund(self):
|
||||
"""
|
||||
Emit an analytics purchase event for this Order. Will iterate over all associated
|
||||
Refund the given order. As of right now, this just marks the order as refunded.
|
||||
"""
|
||||
self.status = 'refunded'
|
||||
self.save()
|
||||
orderitems = OrderItem.objects.filter(order=self).select_subclasses()
|
||||
self._emit_order_event('Refunded Order', orderitems)
|
||||
|
||||
def _emit_order_event(self, event_name, orderitems):
|
||||
"""
|
||||
Emit an analytics event with the given name for this Order. Will iterate over all associated
|
||||
OrderItems and add them as products in the event as well.
|
||||
|
||||
"""
|
||||
event_name = 'Completed Order' # Required event name by Segment
|
||||
try:
|
||||
if settings.FEATURES.get('SEGMENT_IO_LMS') and settings.SEGMENT_IO_LMS_KEY:
|
||||
tracking_context = tracker.get_tracker().resolve_context()
|
||||
@@ -1243,8 +1251,8 @@ class CertificateItem(OrderItem):
|
||||
target_cert.status = 'refunded'
|
||||
target_cert.refund_requested_time = datetime.now(pytz.utc)
|
||||
target_cert.save()
|
||||
target_cert.order.status = 'refunded'
|
||||
target_cert.order.save()
|
||||
|
||||
target_cert.order.refund()
|
||||
|
||||
order_number = target_cert.order_id
|
||||
# send billing an email so they can handle refunding
|
||||
|
||||
@@ -576,6 +576,35 @@ class CertificateItemTest(ModuleStoreTestCase):
|
||||
self.mock_tracker = patcher.start()
|
||||
self.addCleanup(patcher.stop)
|
||||
|
||||
analytics_patcher = patch('shoppingcart.models.analytics')
|
||||
self.mock_analytics_tracker = analytics_patcher.start()
|
||||
self.addCleanup(analytics_patcher.stop)
|
||||
|
||||
def _assert_refund_tracked(self):
|
||||
"""
|
||||
Assert that we fired a refund event.
|
||||
"""
|
||||
self.mock_analytics_tracker.track.assert_called_with( # pylint: disable=maybe-no-member
|
||||
self.user.id,
|
||||
'Refunded Order',
|
||||
{
|
||||
'orderId': 1,
|
||||
'currency': 'usd',
|
||||
'total': '40',
|
||||
'products': [
|
||||
{
|
||||
'sku': u'CertificateItem.verified',
|
||||
'name': unicode(self.course_key),
|
||||
'category': unicode(self.course_key.org),
|
||||
'price': '40',
|
||||
'id': 1,
|
||||
'quantity': 1
|
||||
}
|
||||
]
|
||||
},
|
||||
context={'Google Analytics': {'clientId': None}}
|
||||
)
|
||||
|
||||
def test_existing_enrollment(self):
|
||||
CourseEnrollment.enroll(self.user, self.course_key)
|
||||
cart = Order.get_cart_for_user(user=self.user)
|
||||
@@ -598,18 +627,29 @@ class CertificateItemTest(ModuleStoreTestCase):
|
||||
self.assertEquals(cert_item.single_item_receipt_template,
|
||||
'shoppingcart/receipt.html')
|
||||
|
||||
@override_settings(
|
||||
SEGMENT_IO_LMS_KEY="foobar",
|
||||
FEATURES={
|
||||
'SEGMENT_IO_LMS': True,
|
||||
'STORE_BILLING_INFO': True,
|
||||
}
|
||||
)
|
||||
def test_refund_cert_callback_no_expiration(self):
|
||||
# When there is no expiration date on a verified mode, the user can always get a refund
|
||||
CourseEnrollment.enroll(self.user, self.course_key, 'verified')
|
||||
cart = Order.get_cart_for_user(user=self.user)
|
||||
CertificateItem.add_to_order(cart, self.course_key, self.cost, 'verified')
|
||||
cart.purchase()
|
||||
|
||||
CourseEnrollment.unenroll(self.user, self.course_key)
|
||||
# need to prevent analytics errors from appearing in stderr
|
||||
with patch('sys.stderr', sys.stdout.write):
|
||||
cart.purchase()
|
||||
CourseEnrollment.unenroll(self.user, self.course_key)
|
||||
|
||||
target_certs = CertificateItem.objects.filter(course_id=self.course_key, user_id=self.user, status='refunded', mode='verified')
|
||||
self.assertTrue(target_certs[0])
|
||||
self.assertTrue(target_certs[0].refund_requested_time)
|
||||
self.assertEquals(target_certs[0].order.status, 'refunded')
|
||||
self._assert_refund_tracked()
|
||||
|
||||
def test_no_refund_on_cert_callback(self):
|
||||
# If we explicitly skip refunds, the unenroll action should not modify the purchase.
|
||||
@@ -629,29 +669,40 @@ class CertificateItemTest(ModuleStoreTestCase):
|
||||
self.assertFalse(target_certs[0].refund_requested_time)
|
||||
self.assertEquals(target_certs[0].order.status, 'purchased')
|
||||
|
||||
@override_settings(
|
||||
SEGMENT_IO_LMS_KEY="foobar",
|
||||
FEATURES={
|
||||
'SEGMENT_IO_LMS': True,
|
||||
'STORE_BILLING_INFO': True,
|
||||
}
|
||||
)
|
||||
def test_refund_cert_callback_before_expiration(self):
|
||||
# If the expiration date has not yet passed on a verified mode, the user can be refunded
|
||||
many_days = datetime.timedelta(days=60)
|
||||
|
||||
course = CourseFactory.create()
|
||||
course_key = course.id
|
||||
course_mode = CourseMode(course_id=course_key,
|
||||
self.course_key = course.id
|
||||
course_mode = CourseMode(course_id=self.course_key,
|
||||
mode_slug="verified",
|
||||
mode_display_name="verified cert",
|
||||
min_price=self.cost,
|
||||
expiration_datetime=(datetime.datetime.now(pytz.utc) + many_days))
|
||||
course_mode.save()
|
||||
|
||||
CourseEnrollment.enroll(self.user, course_key, 'verified')
|
||||
CourseEnrollment.enroll(self.user, self.course_key, 'verified')
|
||||
cart = Order.get_cart_for_user(user=self.user)
|
||||
CertificateItem.add_to_order(cart, course_key, self.cost, 'verified')
|
||||
cart.purchase()
|
||||
CertificateItem.add_to_order(cart, self.course_key, self.cost, 'verified')
|
||||
|
||||
CourseEnrollment.unenroll(self.user, course_key)
|
||||
target_certs = CertificateItem.objects.filter(course_id=course_key, user_id=self.user, status='refunded', mode='verified')
|
||||
# need to prevent analytics errors from appearing in stderr
|
||||
with patch('sys.stderr', sys.stdout.write):
|
||||
cart.purchase()
|
||||
CourseEnrollment.unenroll(self.user, self.course_key)
|
||||
|
||||
target_certs = CertificateItem.objects.filter(course_id=self.course_key, user_id=self.user, status='refunded', mode='verified')
|
||||
self.assertTrue(target_certs[0])
|
||||
self.assertTrue(target_certs[0].refund_requested_time)
|
||||
self.assertEquals(target_certs[0].order.status, 'refunded')
|
||||
self._assert_refund_tracked()
|
||||
|
||||
def test_refund_cert_callback_before_expiration_email(self):
|
||||
""" Test that refund emails are being sent correctly. """
|
||||
|
||||
Reference in New Issue
Block a user