From fb93aeb2f4eccd09726af38bee02ffcbbc9976f1 Mon Sep 17 00:00:00 2001 From: "Glenn R. Martin" Date: Wed, 3 Jul 2024 11:21:39 -0400 Subject: [PATCH 1/9] fix: Passing paypal variable through to checkout if set SONIC-501 --- ecommerce/coupons/views.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ecommerce/coupons/views.py b/ecommerce/coupons/views.py index f8a78968890..fb6b12e5d8e 100644 --- a/ecommerce/coupons/views.py +++ b/ecommerce/coupons/views.py @@ -147,7 +147,6 @@ def get(self, request, *args, **kwargs): """Get method for coupon redemption page.""" return super(CouponOfferView, self).get(request, *args, **kwargs) - class CouponRedeemView(EdxOrderPlacementMixin, APIView): permission_classes = (LoginRedirectIfUnauthenticated,) @@ -303,7 +302,13 @@ def get(self, request): # pylint: disable=too-many-statements # and should not display the payment form before making that determination. # TODO: It would be cleaner if the user could be redirected to their final destination up front. redirect_url = get_payment_microfrontend_or_basket_url(self.request) + "?coupon_redeem_redirect=1" + + # Check for the paypal=true parameter from the ecommerece checkout and add it to the redirect URL if present + if request.GET.get('paypal') == 'true': + redirect_url += "&paypal=true" + redirect_url = add_stripe_flag_to_url(redirect_url, self.request) + return HttpResponseRedirect(redirect_url) From aac323ff2e12fa6b1d837a2e7da155d2be7eaf60 Mon Sep 17 00:00:00 2001 From: "Glenn R. Martin" Date: Wed, 3 Jul 2024 11:28:07 -0400 Subject: [PATCH 2/9] fix: latest patch --- ecommerce/coupons/views.py | 8 +++++--- ecommerce/extensions/basket/views.py | 6 ++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/ecommerce/coupons/views.py b/ecommerce/coupons/views.py index fb6b12e5d8e..ee3f4485eeb 100644 --- a/ecommerce/coupons/views.py +++ b/ecommerce/coupons/views.py @@ -303,9 +303,11 @@ def get(self, request): # pylint: disable=too-many-statements # TODO: It would be cleaner if the user could be redirected to their final destination up front. redirect_url = get_payment_microfrontend_or_basket_url(self.request) + "?coupon_redeem_redirect=1" - # Check for the paypal=true parameter from the ecommerece checkout and add it to the redirect URL if present - if request.GET.get('paypal') == 'true': - redirect_url += "&paypal=true" + # Check for the paypal_redirect=1 parameter from the ecommerece checkout and add it to the redirect URL if present + paypal_redirect = request.GET.get('paypal_redirect') + + if paypal_redirect: + redirect_url += "&paypal_redirect=1" redirect_url = add_stripe_flag_to_url(redirect_url, self.request) diff --git a/ecommerce/extensions/basket/views.py b/ecommerce/extensions/basket/views.py index 241655e789d..e8ac67c86a8 100644 --- a/ecommerce/extensions/basket/views.py +++ b/ecommerce/extensions/basket/views.py @@ -492,6 +492,12 @@ def _redirect_response_to_basket_or_payment(self, request, invalid_code=None): redirect_url = get_payment_microfrontend_or_basket_url(request) redirect_url = add_utm_params_to_url(redirect_url, list(self.request.GET.items())) redirect_url = add_invalid_code_message_to_url(redirect_url, invalid_code) + + # Check for the paypal_redirect=1 parameter from the ecommerece checkout and add it to the redirect URL if present + paypal_redirect = request.GET.get('paypal_redirect') + + if paypal_redirect: + redirect_url += "?paypal_redirect=1" redirect_url = add_stripe_flag_to_url(redirect_url, request) return HttpResponseRedirect(redirect_url, status=303) From 45499ec05d975b1f599d22206efd02031ec4434d Mon Sep 17 00:00:00 2001 From: "Glenn R. Martin" Date: Wed, 3 Jul 2024 11:58:33 -0400 Subject: [PATCH 3/9] fix: code styling rules --- ecommerce/coupons/views.py | 1 + ecommerce/extensions/basket/views.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ecommerce/coupons/views.py b/ecommerce/coupons/views.py index ee3f4485eeb..8bf80aa3a7d 100644 --- a/ecommerce/coupons/views.py +++ b/ecommerce/coupons/views.py @@ -147,6 +147,7 @@ def get(self, request, *args, **kwargs): """Get method for coupon redemption page.""" return super(CouponOfferView, self).get(request, *args, **kwargs) + class CouponRedeemView(EdxOrderPlacementMixin, APIView): permission_classes = (LoginRedirectIfUnauthenticated,) diff --git a/ecommerce/extensions/basket/views.py b/ecommerce/extensions/basket/views.py index e8ac67c86a8..d73a9f0736c 100644 --- a/ecommerce/extensions/basket/views.py +++ b/ecommerce/extensions/basket/views.py @@ -493,7 +493,7 @@ def _redirect_response_to_basket_or_payment(self, request, invalid_code=None): redirect_url = add_utm_params_to_url(redirect_url, list(self.request.GET.items())) redirect_url = add_invalid_code_message_to_url(redirect_url, invalid_code) - # Check for the paypal_redirect=1 parameter from the ecommerece checkout and add it to the redirect URL if present + # Check for the paypal_redirect=1 parameter from the ecommerece checkout and add it to the redirect URL if present paypal_redirect = request.GET.get('paypal_redirect') if paypal_redirect: From b73add6b586de2001df4c433373e5ac7aa1d4c42 Mon Sep 17 00:00:00 2001 From: "Glenn R. Martin" Date: Wed, 3 Jul 2024 12:20:25 -0400 Subject: [PATCH 4/9] fix: more quality --- ecommerce/coupons/views.py | 3 ++- ecommerce/extensions/basket/views.py | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/ecommerce/coupons/views.py b/ecommerce/coupons/views.py index 8bf80aa3a7d..7b13423c4af 100644 --- a/ecommerce/coupons/views.py +++ b/ecommerce/coupons/views.py @@ -304,7 +304,8 @@ def get(self, request): # pylint: disable=too-many-statements # TODO: It would be cleaner if the user could be redirected to their final destination up front. redirect_url = get_payment_microfrontend_or_basket_url(self.request) + "?coupon_redeem_redirect=1" - # Check for the paypal_redirect=1 parameter from the ecommerece checkout and add it to the redirect URL if present + # Check for the paypal_redirect=1 parameter from the ecommerece checkout and add it to the + # redirect URL if present paypal_redirect = request.GET.get('paypal_redirect') if paypal_redirect: diff --git a/ecommerce/extensions/basket/views.py b/ecommerce/extensions/basket/views.py index d73a9f0736c..0d5084ffe8c 100644 --- a/ecommerce/extensions/basket/views.py +++ b/ecommerce/extensions/basket/views.py @@ -493,11 +493,13 @@ def _redirect_response_to_basket_or_payment(self, request, invalid_code=None): redirect_url = add_utm_params_to_url(redirect_url, list(self.request.GET.items())) redirect_url = add_invalid_code_message_to_url(redirect_url, invalid_code) - # Check for the paypal_redirect=1 parameter from the ecommerece checkout and add it to the redirect URL if present + # Check for the paypal_redirect=1 parameter from the ecommerece checkout and add it to the + # redirect URL if present paypal_redirect = request.GET.get('paypal_redirect') if paypal_redirect: - redirect_url += "?paypal_redirect=1" + concat_char = "&" if "?" in redirect_url else "?" + redirect_url += f"{concat_char}paypal_redirect=1" redirect_url = add_stripe_flag_to_url(redirect_url, request) return HttpResponseRedirect(redirect_url, status=303) From 83bae38b0aeb3b092dcaba4da4af0994be59dbc2 Mon Sep 17 00:00:00 2001 From: "Glenn R. Martin" Date: Wed, 3 Jul 2024 12:25:46 -0400 Subject: [PATCH 5/9] fix: concat from Shafqat --- ecommerce/extensions/basket/views.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ecommerce/extensions/basket/views.py b/ecommerce/extensions/basket/views.py index 0d5084ffe8c..caa5ea27319 100644 --- a/ecommerce/extensions/basket/views.py +++ b/ecommerce/extensions/basket/views.py @@ -498,8 +498,9 @@ def _redirect_response_to_basket_or_payment(self, request, invalid_code=None): paypal_redirect = request.GET.get('paypal_redirect') if paypal_redirect: - concat_char = "&" if "?" in redirect_url else "?" - redirect_url += f"{concat_char}paypal_redirect=1" + redirect_url += '&' if '?' in redirect_url else '?' + redirect_url += 'paypal_redirect=1' + redirect_url = add_stripe_flag_to_url(redirect_url, request) return HttpResponseRedirect(redirect_url, status=303) From 1973abb6f00de4c0f088af6f13b202a63369333f Mon Sep 17 00:00:00 2001 From: Chris Pappas Date: Wed, 3 Jul 2024 14:31:37 -0400 Subject: [PATCH 6/9] fix: semi-temp fix to pin pip/pip-tools versions to prevent pip install failures (#4170) --- .github/workflows/migrations-mysql8.yml | 1 + requirements/pip_tools.in | 2 +- requirements/pip_tools.txt | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/migrations-mysql8.yml b/.github/workflows/migrations-mysql8.yml index c03b8ef9956..2394c14eb9a 100644 --- a/.github/workflows/migrations-mysql8.yml +++ b/.github/workflows/migrations-mysql8.yml @@ -48,6 +48,7 @@ jobs: mysql -V - name: Install Python dependencies run: | + pip install pip==21.2.1 --upgrade # set pip version to be compatible with deprecated pip version syntax pip install -r requirements/pip_tools.txt pip install -r requirements/production.txt pip uninstall -y mysqlclient diff --git a/requirements/pip_tools.in b/requirements/pip_tools.in index f2177985a94..bee11765df0 100644 --- a/requirements/pip_tools.in +++ b/requirements/pip_tools.in @@ -1,4 +1,4 @@ -c constraints.txt # Dependencies to run compile tools -pip-tools # Contains pip-compile, used to generate pip requirements files +pip-tools==6.0 # Contains pip-compile, used to generate pip requirements files diff --git a/requirements/pip_tools.txt b/requirements/pip_tools.txt index b6150065453..669c1f956a0 100644 --- a/requirements/pip_tools.txt +++ b/requirements/pip_tools.txt @@ -10,7 +10,7 @@ click==8.1.3 # via pip-tools packaging==23.1 # via build -pip-tools==6.13.0 +pip-tools==6.0 # via -r requirements/pip_tools.in pyproject-hooks==1.0.0 # via build From ca87ce3de2e6422188c10ddb7c644ad411211d3d Mon Sep 17 00:00:00 2001 From: "Glenn R. Martin" Date: Wed, 3 Jul 2024 14:47:55 -0400 Subject: [PATCH 7/9] fix: typo --- ecommerce/coupons/views.py | 2 +- ecommerce/extensions/basket/views.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ecommerce/coupons/views.py b/ecommerce/coupons/views.py index 7b13423c4af..f195c66ef22 100644 --- a/ecommerce/coupons/views.py +++ b/ecommerce/coupons/views.py @@ -304,7 +304,7 @@ def get(self, request): # pylint: disable=too-many-statements # TODO: It would be cleaner if the user could be redirected to their final destination up front. redirect_url = get_payment_microfrontend_or_basket_url(self.request) + "?coupon_redeem_redirect=1" - # Check for the paypal_redirect=1 parameter from the ecommerece checkout and add it to the + # Check for the paypal_redirect=1 parameter from the ecommerce checkout and add it to the # redirect URL if present paypal_redirect = request.GET.get('paypal_redirect') diff --git a/ecommerce/extensions/basket/views.py b/ecommerce/extensions/basket/views.py index caa5ea27319..1bd33ab52fe 100644 --- a/ecommerce/extensions/basket/views.py +++ b/ecommerce/extensions/basket/views.py @@ -493,7 +493,7 @@ def _redirect_response_to_basket_or_payment(self, request, invalid_code=None): redirect_url = add_utm_params_to_url(redirect_url, list(self.request.GET.items())) redirect_url = add_invalid_code_message_to_url(redirect_url, invalid_code) - # Check for the paypal_redirect=1 parameter from the ecommerece checkout and add it to the + # Check for the paypal_redirect=1 parameter from the ecommerce checkout and add it to the # redirect URL if present paypal_redirect = request.GET.get('paypal_redirect') From d9c25319c6cd28de2f5f77d656f6d80b303c14c8 Mon Sep 17 00:00:00 2001 From: "Glenn R. Martin" Date: Fri, 5 Jul 2024 10:42:20 -0400 Subject: [PATCH 8/9] fix: Adding test for basket paypal redirect qs param --- ecommerce/extensions/basket/tests/test_views.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ecommerce/extensions/basket/tests/test_views.py b/ecommerce/extensions/basket/tests/test_views.py index 52a56f7306e..610dc4e5f76 100644 --- a/ecommerce/extensions/basket/tests/test_views.py +++ b/ecommerce/extensions/basket/tests/test_views.py @@ -119,6 +119,16 @@ def test_basket_with_utm_params(self): expected_url = self.get_full_url(reverse('basket:summary')) + '?utm_source=test' self.assertEqual(response.url, expected_url) + def test_basket_with_paypal_param(self): + """ Verify the basket includes paypal param after redirect. """ + products = ProductFactory.create_batch(3, stockrecords__partner=self.partner) + response = self._get_response( + [product.stockrecords.first().partner_sku for product in products], + paypal_redirect='1', + ) + expected_url = self.get_full_url(reverse('basket:summary')) + '?paypal_redirect=1' + self.assertEqual(response.url, expected_url) + @responses.activate def test_redirect_to_basket_summary(self): """ From d9ab2716dd75031ca657f44f430140c1b5d61997 Mon Sep 17 00:00:00 2001 From: "Glenn R. Martin" Date: Fri, 5 Jul 2024 11:12:22 -0400 Subject: [PATCH 9/9] fix: coupon redirect testing for qs addition of paypal redirect --- ecommerce/coupons/tests/test_views.py | 29 ++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/ecommerce/coupons/tests/test_views.py b/ecommerce/coupons/tests/test_views.py index 24a81b5252e..2ec4ba1c369 100644 --- a/ecommerce/coupons/tests/test_views.py +++ b/ecommerce/coupons/tests/test_views.py @@ -342,7 +342,7 @@ def tearDown(self): super().tearDown() responses.reset() - def redeem_url_with_params(self, code=COUPON_CODE, consent_token=None): + def redeem_url_with_params(self, code=COUPON_CODE, consent_token=None, other_qs_params=None): """ Constructs the coupon redemption URL with the proper string query parameters. """ params = { 'code': code, @@ -350,6 +350,8 @@ def redeem_url_with_params(self, code=COUPON_CODE, consent_token=None): } if consent_token is not None: params['consent_token'] = consent_token + if other_qs_params is not None: + params.update(other_qs_params) return format_url(base=self.redeem_url, params=params) def create_coupon_and_get_code( @@ -387,9 +389,12 @@ def create_coupon_and_get_code( self.assertEqual(Voucher.objects.filter(code=coupon_code).count(), 1) return coupon_code, coupon - def redeem_coupon(self, code=COUPON_CODE, consent_token=None): + def redeem_coupon(self, code=COUPON_CODE, consent_token=None, other_qs_params=None): self.request.user = self.user - return self.client.get(self.redeem_url_with_params(code=code, consent_token=consent_token)) + return self.client.get(self.redeem_url_with_params( + code=code, + consent_token=consent_token, + other_qs_params=other_qs_params)) def assert_redirects_to_receipt_page(self, code=COUPON_CODE, consent_token=None): response = self.redeem_coupon(code=code, consent_token=consent_token) @@ -406,9 +411,10 @@ def assert_redirects_to_receipt_page(self, code=COUPON_CODE, consent_token=None) self.assertRedirects(response, expected_url, status_code=302, fetch_redirect_response=False) - def assert_redemption_page_redirects(self, expected_url, target=200, code=COUPON_CODE, consent_token=None): + def assert_redemption_page_redirects(self, expected_url, target=200, code=COUPON_CODE, + consent_token=None, other_qs_params=None): """ Verify redirect from redeem page to expected page. """ - response = self.redeem_coupon(code=code, consent_token=consent_token) + response = self.redeem_coupon(code=code, consent_token=consent_token, other_qs_params=other_qs_params) self.assertRedirects( response, expected_url, status_code=302, target_status_code=target, fetch_redirect_response=False ) @@ -495,6 +501,19 @@ def test_basket_redirect_discount_code(self): self.create_coupon(catalog=self.catalog, code=COUPON_CODE, benefit_value=5) self.assert_redemption_page_redirects(self.get_coupon_redeem_success_expected_redirect_url()) + @responses.activate + def test_basket_redirect_discount_code_with_paypal(self): + """ Verify the view redirects to the basket view when a discount code is provided with a paypal qs param. """ + self.mock_course_api_response(course=self.course) + self.mock_account_api(self.request, self.user.username, data={'is_active': True}) + self.mock_access_token_response() + + self.create_coupon(catalog=self.catalog, code=COUPON_CODE, benefit_value=5) + self.assert_redemption_page_redirects( + self.get_coupon_redeem_success_expected_redirect_url() + '&paypal_redirect=1', + other_qs_params={'paypal_redirect': '1'} + ) + @override_flag(REDIRECT_WITH_WAFFLE_TESTING_QUERYSTRING, active=True) @responses.activate def test_basket_redirect_discount_code_with_waffle(self):