Skip to content
This repository has been archived by the owner on Nov 4, 2024. It is now read-only.

fix: account for refunds in exec ed 2u redemption flow #3920

Merged
merged 5 commits into from
Mar 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions ecommerce/extensions/executive_education_2u/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
from ecommerce.extensions.executive_education_2u.constants import ExecutiveEducation2UCheckoutFailureReason
from ecommerce.extensions.executive_education_2u.utils import get_previous_order_for_user
from ecommerce.extensions.fulfillment.status import ORDER
from ecommerce.extensions.refund.status import REFUND
from ecommerce.extensions.refund.tests.factories import RefundFactory
from ecommerce.extensions.test import factories
from ecommerce.tests.mixins import JwtMixin
from ecommerce.tests.testcases import TestCase
Expand Down Expand Up @@ -130,6 +132,57 @@ def test_begin_checkout_has_previous_order_redirect_to_receipt_page(self):
)
self.assertEqual(response.headers['Location'], expected_redirect_url)

def test_begin_checkout_has_previous_order_refund_error_redirect_to_receipt_page(self):
product = self._create_product(is_exec_ed_2u_product=True)
sku = product.stockrecords.first().partner_sku
order = OrderFactory(user=self.user)
OrderLineFactory(order=order, product=product, partner_sku=sku)
RefundFactory(order=order, user=self.user, status=REFUND.PAYMENT_REFUND_ERROR)

response = self.client.get(self.checkout_path, {'sku': sku})
self.assertEqual(response.status_code, status.HTTP_302_FOUND)

expected_redirect_url = get_receipt_page_url(
response.request,
order_number=order.number,
site_configuration=order.site.siteconfiguration,
disable_back_button=False
)
self.assertEqual(response.headers['Location'], expected_redirect_url)

@mock.patch('ecommerce.enterprise.conditions.catalog_contains_course_runs')
@mock.patch('ecommerce.enterprise.conditions.get_course_info_from_catalog')
@mock.patch('ecommerce.extensions.executive_education_2u.views.get_learner_portal_url')
def test_begin_checkout_has_previous_refunded_order_redirect_to_lp(
self,
mock_get_learner_portal_url,
mock_get_course_info_from_catalog,
mock_catalog_contains_course_runs
):
mock_get_learner_portal_url.return_value = self.learner_portal_url
product = self._create_product(is_exec_ed_2u_product=True)
sku = product.stockrecords.first().partner_sku
self._create_enterprise_offer()

order = OrderFactory(user=self.user)
OrderLineFactory(order=order, product=product, partner_sku=sku)
RefundFactory(order=order, user=self.user, status=REFUND.COMPLETE)

mock_get_course_info_from_catalog.return_value = {
'key': product.attr.UUID
}
mock_catalog_contains_course_runs.return_value = True

response = self.client.get(self.checkout_path, {'sku': sku})
self.assertEqual(response.status_code, status.HTTP_302_FOUND)

expected_query_params = {
'course_uuid': product.attr.UUID,
'sku': sku
}
expected_redirect_url = f'{self.learner_portal_url}/executive-education-2u?{urlencode(expected_query_params)}'
self.assertEqual(response.headers['Location'], expected_redirect_url)

@mock.patch('ecommerce.enterprise.conditions.catalog_contains_course_runs')
@mock.patch('ecommerce.enterprise.conditions.get_course_info_from_catalog')
@mock.patch('ecommerce.extensions.executive_education_2u.views.get_learner_portal_url')
Expand Down
11 changes: 9 additions & 2 deletions ecommerce/extensions/executive_education_2u/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from ecommerce.courses.constants import CertificateType
from ecommerce.enterprise.api import get_enterprise_id_for_user
from ecommerce.enterprise.utils import get_enterprise_customer
from ecommerce.extensions.refund.status import REFUND

Product = get_model('catalogue', 'Product')
Order = get_model('order', 'Order')
Expand All @@ -32,8 +33,14 @@ def get_executive_education_2u_product(partner, sku):


def get_previous_order_for_user(user, product):
# TODO: figure out if users can place orders multiple times
return Order.objects.filter(user=user, lines__product=product).first()
"""
Find previous non-refunded order for product from user.
"""
return Order.objects \
.filter(user=user, lines__product=product) \
.prefetch_related('refunds') \
.filter(Q(refunds__isnull=True) | ~Q(refunds__status=REFUND.COMPLETE)) \
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Finds order with no refunds OR orders with incomplete refunds.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: you can end lines with an opening parenthesis and close on the next line to break this across lines, instead of using \. e.g.

return Order.objects.filter(
    user=user, lines__product=product
).prefetch_related(
    'refunds'
)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yeah that is true, though, I think I'll leave it as is with the \ given that its 5 lines vs. 7 lines, and personally (imo) a bit easier to read when the args are on the same line as the method being called.

.first()


def get_learner_portal_url(request):
Expand Down
2 changes: 1 addition & 1 deletion ecommerce/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,7 @@
# Cache enterprise response from Enterprise API.
ENTERPRISE_API_CACHE_TIMEOUT = 300 # Value is in seconds

ENTERPRISE_CATALOG_SERVICE_URL = 'http://localhost:18160/'
ENTERPRISE_CATALOG_SERVICE_URL = 'http://enterprise.catalog.app:18160/'
Copy link
Contributor Author

@adamstankiewicz adamstankiewicz Mar 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ended up needing to change this setting to get something to work when re-setting up all my devstack/enterprise IDAs but don't quite remember exactly what...


ENTERPRISE_ANALYTICS_API_URL = 'http://localhost:19001'

Expand Down