Commit 85bfca9d by Vedran Karacic Committed by Vedran Karačić

Revert "Change enrollment code redemption to the receipt page."

This reverts commit ea2abdf9.
parent ea2abdf9
import datetime import datetime
import urllib import urllib
import ddt
import httpretty import httpretty
import mock
import pytz import pytz
from django.conf import settings from django.conf import settings
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
...@@ -22,9 +20,6 @@ from ecommerce.coupons.views import voucher_is_valid ...@@ -22,9 +20,6 @@ from ecommerce.coupons.views import voucher_is_valid
from ecommerce.courses.tests.factories import CourseFactory from ecommerce.courses.tests.factories import CourseFactory
from ecommerce.extensions.api import exceptions from ecommerce.extensions.api import exceptions
from ecommerce.extensions.catalogue.tests.mixins import CourseCatalogTestMixin from ecommerce.extensions.catalogue.tests.mixins import CourseCatalogTestMixin
from ecommerce.extensions.checkout.mixins import EdxOrderPlacementMixin
from ecommerce.extensions.checkout.utils import get_receipt_page_url
from ecommerce.extensions.fulfillment.status import ORDER
from ecommerce.extensions.test.factories import prepare_voucher from ecommerce.extensions.test.factories import prepare_voucher
from ecommerce.extensions.voucher.utils import get_voucher_and_products_from_code from ecommerce.extensions.voucher.utils import get_voucher_and_products_from_code
from ecommerce.tests.mixins import ApiMockMixin, LmsApiMockMixin from ecommerce.tests.mixins import ApiMockMixin, LmsApiMockMixin
...@@ -36,7 +31,6 @@ Benefit = get_model('offer', 'Benefit') ...@@ -36,7 +31,6 @@ Benefit = get_model('offer', 'Benefit')
Catalog = get_model('catalogue', 'Catalog') Catalog = get_model('catalogue', 'Catalog')
Course = get_model('courses', 'Course') Course = get_model('courses', 'Course')
Product = get_model('catalogue', 'Product') Product = get_model('catalogue', 'Product')
Order = get_model('order', 'Order')
OrderLineVouchers = get_model('voucher', 'OrderLineVouchers') OrderLineVouchers = get_model('voucher', 'OrderLineVouchers')
StockRecord = get_model('partner', 'StockRecord') StockRecord = get_model('partner', 'StockRecord')
Voucher = get_model('voucher', 'Voucher') Voucher = get_model('voucher', 'Voucher')
...@@ -268,7 +262,6 @@ class CouponOfferViewTests(ApiMockMixin, CouponMixin, CourseCatalogTestMixin, Lm ...@@ -268,7 +262,6 @@ class CouponOfferViewTests(ApiMockMixin, CouponMixin, CourseCatalogTestMixin, Lm
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
@ddt.ddt
class CouponRedeemViewTests(CouponMixin, CourseCatalogTestMixin, LmsApiMockMixin, TestCase): class CouponRedeemViewTests(CouponMixin, CourseCatalogTestMixin, LmsApiMockMixin, TestCase):
redeem_url = reverse('coupons:redeem') redeem_url = reverse('coupons:redeem')
...@@ -286,6 +279,7 @@ class CouponRedeemViewTests(CouponMixin, CourseCatalogTestMixin, LmsApiMockMixin ...@@ -286,6 +279,7 @@ class CouponRedeemViewTests(CouponMixin, CourseCatalogTestMixin, LmsApiMockMixin
self.stock_record = StockRecord.objects.get(product=self.seat) self.stock_record = StockRecord.objects.get(product=self.seat)
self.catalog = Catalog.objects.create(partner=self.partner) self.catalog = Catalog.objects.create(partner=self.partner)
self.catalog.stock_records.add(StockRecord.objects.get(product=self.seat)) self.catalog.stock_records.add(StockRecord.objects.get(product=self.seat))
self.student_dashboard_url = get_lms_url(self.site.siteconfiguration.student_dashboard_url)
def redeem_url_with_params(self, code=COUPON_CODE): def redeem_url_with_params(self, code=COUPON_CODE):
""" Constructs the coupon redemption URL with the proper string query parameters. """ """ Constructs the coupon redemption URL with the proper string query parameters. """
...@@ -303,23 +297,12 @@ class CouponRedeemViewTests(CouponMixin, CourseCatalogTestMixin, LmsApiMockMixin ...@@ -303,23 +297,12 @@ class CouponRedeemViewTests(CouponMixin, CourseCatalogTestMixin, LmsApiMockMixin
self.assertEqual(Voucher.objects.filter(code=coupon_code).count(), 1) self.assertEqual(Voucher.objects.filter(code=coupon_code).count(), 1)
return coupon_code return coupon_code
def assert_redemption_page_redirects(self, expected_url, target=200, code=COUPON_CODE, query_string=''): def assert_redemption_page_redirects(self, expected_url, target=200, code=COUPON_CODE):
""" Verify redirect from redeem page to expected page. """ """ Verify redirect from redeem page to expected page. """
self.request.user = self.user self.request.user = self.user
self.mock_enrollment_api(self.request, self.user, self.course.id, is_active=False, mode=self.course_mode) self.mock_enrollment_api(self.request, self.user, self.course.id, is_active=False, mode=self.course_mode)
response = self.client.get(self.redeem_url_with_params(code=code)) response = self.client.get(self.redeem_url_with_params(code=code))
self.assertRedirects(response, expected_url, status_code=302, target_status_code=target)
if query_string:
order = Order.objects.first()
expected_url = '{url}?{query_string}={order_num}'.format(
url=expected_url,
query_string=query_string,
order_num=order.number
)
self.assertRedirects(
response, expected_url, status_code=302, target_status_code=target, fetch_redirect_response=False
)
def test_login_required(self): def test_login_required(self):
""" Users are required to login before accessing the view. """ """ Users are required to login before accessing the view. """
...@@ -375,75 +358,29 @@ class CouponRedeemViewTests(CouponMixin, CourseCatalogTestMixin, LmsApiMockMixin ...@@ -375,75 +358,29 @@ class CouponRedeemViewTests(CouponMixin, CourseCatalogTestMixin, LmsApiMockMixin
self.assert_redemption_page_redirects(expected_url) self.assert_redemption_page_redirects(expected_url)
@httpretty.activate @httpretty.activate
@ddt.data( def test_basket_redirect_enrollment_code(self):
(True, 'order_number'), """ Verify the view redirects to LMS when an enrollment code is provided. """
(False, 'orderNum')
)
@ddt.unpack
def test_basket_redirect_enrollment_code(self, ecomm_receipt, query_string):
""" Verify the view redirects to a receipt page when an enrollment code is provided. """
self.toggle_ecommerce_receipt_page(ecomm_receipt)
code = self.create_and_test_coupon_and_return_code(benefit_value=100, code='') code = self.create_and_test_coupon_and_return_code(benefit_value=100, code='')
receipt_page_url = get_receipt_page_url(self.site.siteconfiguration) httpretty.register_uri(httpretty.GET, self.student_dashboard_url, status=status.HTTP_301_MOVED_PERMANENTLY)
enrollment_api_url = '{root}{enrollment}'.format(
root=self.site.siteconfiguration.enrollment_api_url,
enrollment='enrollment'
)
httpretty.register_uri(httpretty.POST, enrollment_api_url, status=status.HTTP_200_OK)
httpretty.register_uri(httpretty.GET, receipt_page_url, status=status.HTTP_301_MOVED_PERMANENTLY)
self.mock_account_api(self.request, self.user.username, data={'is_active': True}) self.mock_account_api(self.request, self.user.username, data={'is_active': True})
self.assert_redemption_page_redirects( self.assert_redemption_page_redirects(
receipt_page_url, self.student_dashboard_url,
target=status.HTTP_301_MOVED_PERMANENTLY,
code=code,
query_string=query_string
)
@httpretty.activate
@mock.patch.object(EdxOrderPlacementMixin, 'place_free_order')
def test_basket_redirect_enrollment_code_error(self, place_free_order):
""" Verify the view redirects to checkout error page when an order is not completed. """
code = self.create_and_test_coupon_and_return_code(benefit_value=100, code='')
self.mock_account_api(self.request, self.user.username, data={'is_active': True})
open_order = OrderFactory(status=ORDER.OPEN)
place_free_order.return_value = open_order
self.assert_redemption_page_redirects(
self.get_full_url(reverse('checkout:error')),
target=status.HTTP_301_MOVED_PERMANENTLY, target=status.HTTP_301_MOVED_PERMANENTLY,
code=code code=code
) )
@httpretty.activate @httpretty.activate
@ddt.data( def test_multiple_vouchers(self):
(True, 'order_number'),
(False, 'orderNum')
)
@ddt.unpack
def test_multiple_vouchers(self, ecomm_receipt, query_string):
""" Verify a redirect to LMS happens when a basket with already existing vouchers is used. """ """ Verify a redirect to LMS happens when a basket with already existing vouchers is used. """
self.toggle_ecommerce_receipt_page(ecomm_receipt)
receipt_page_url = get_receipt_page_url(self.site.siteconfiguration)
code = self.create_and_test_coupon_and_return_code(benefit_value=100, code='') code = self.create_and_test_coupon_and_return_code(benefit_value=100, code='')
basket = Basket.get_basket(self.user, self.site) basket = Basket.get_basket(self.user, self.site)
basket.vouchers.add(Voucher.objects.get(code=code)) basket.vouchers.add(Voucher.objects.get(code=code))
enrollment_api_url = '{root}{enrollment}'.format(
root=self.site.siteconfiguration.enrollment_api_url,
enrollment='enrollment'
)
httpretty.register_uri(httpretty.POST, enrollment_api_url, status=status.HTTP_200_OK)
self.mock_account_api(self.request, self.user.username, data={'is_active': True}) self.mock_account_api(self.request, self.user.username, data={'is_active': True})
httpretty.register_uri(httpretty.GET, receipt_page_url, status=status.HTTP_301_MOVED_PERMANENTLY) httpretty.register_uri(httpretty.GET, self.student_dashboard_url, status=status.HTTP_301_MOVED_PERMANENTLY)
self.assert_redemption_page_redirects( self.assert_redemption_page_redirects(
receipt_page_url, self.student_dashboard_url,
target=status.HTTP_301_MOVED_PERMANENTLY, target=status.HTTP_301_MOVED_PERMANENTLY,
code=code, code=code
query_string=query_string
) )
@httpretty.activate @httpretty.activate
......
...@@ -2,7 +2,6 @@ from __future__ import unicode_literals ...@@ -2,7 +2,6 @@ from __future__ import unicode_literals
import csv import csv
import logging import logging
import time
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
...@@ -22,8 +21,6 @@ from ecommerce.coupons.decorators import login_required_for_credit ...@@ -22,8 +21,6 @@ from ecommerce.coupons.decorators import login_required_for_credit
from ecommerce.extensions.api import exceptions from ecommerce.extensions.api import exceptions
from ecommerce.extensions.basket.utils import prepare_basket from ecommerce.extensions.basket.utils import prepare_basket
from ecommerce.extensions.checkout.mixins import EdxOrderPlacementMixin from ecommerce.extensions.checkout.mixins import EdxOrderPlacementMixin
from ecommerce.extensions.checkout.utils import get_receipt_page_url
from ecommerce.extensions.fulfillment.status import ORDER
from ecommerce.extensions.voucher.utils import get_voucher_and_products_from_code from ecommerce.extensions.voucher.utils import get_voucher_and_products_from_code
Applicator = get_class('offer.utils', 'Applicator') Applicator = get_class('offer.utils', 'Applicator')
...@@ -164,22 +161,11 @@ class CouponRedeemView(EdxOrderPlacementMixin, View): ...@@ -164,22 +161,11 @@ class CouponRedeemView(EdxOrderPlacementMixin, View):
basket = prepare_basket(request, product, voucher) basket = prepare_basket(request, product, voucher)
if basket.total_excl_tax == 0: if basket.total_excl_tax == 0:
order = self.place_free_order(basket) self.place_free_order(basket)
else:
# Waiting for the order to finish its async fulfillment. return HttpResponseRedirect(reverse('basket:summary'))
# Every 2 seconds the order status is checked. If after five checks
# it's not complete or the status is an error, user is redirected return HttpResponseRedirect(request.site.siteconfiguration.student_dashboard_url)
# to the checkout error page.
for __ in range(5): # pragma: no cover
order.refresh_from_db()
if order.status == ORDER.COMPLETE:
return HttpResponseRedirect(get_receipt_page_url(self.request.site.siteconfiguration, order.number))
elif order.status == ORDER.FULFILLMENT_ERROR:
return HttpResponseRedirect(reverse('checkout:error'))
time.sleep(2) # pragma: no cover
return HttpResponseRedirect(reverse('checkout:error'))
return HttpResponseRedirect(reverse('basket:summary'))
class EnrollmentCodeCsvView(View): class EnrollmentCodeCsvView(View):
......
...@@ -150,19 +150,6 @@ define([ ...@@ -150,19 +150,6 @@ define([
expect(view.collection.previousPage).toHaveBeenCalled(); expect(view.collection.previousPage).toHaveBeenCalled();
}); });
it('should disable the enrollment button', function() {
var ev = $.Event('click');
$('body').append('<a class="btn-success redeem-enrollment"></a>');
view.disableReedemEnrollmentBtn(ev);
expect(ev.isDefaultPrevented()).toBeFalsy();
expect($('.redeem-enrollment').attr('disabled')).toEqual('disabled');
expect($('.redeem-enrollment').hasClass('btn-default')).toBeTruthy();
expect($('.redeem-enrollment').hasClass('btn-success')).toBeFalsy();
view.disableReedemEnrollmentBtn(ev);
expect(ev.isDefaultPrevented()).toBeTruthy();
});
it('should create list item', function() { it('should create list item', function() {
var value = view.createListItem(1, false), var value = view.createListItem(1, false),
string = '<li class="page-item">' + string = '<li class="page-item">' +
......
...@@ -24,8 +24,7 @@ define([ ...@@ -24,8 +24,7 @@ define([
events: { events: {
'click .prev': 'previous', 'click .prev': 'previous',
'click .next': 'next', 'click .next': 'next',
'click .page-number': 'goToPage', 'click .page-number': 'goToPage'
'click .redeem-enrollment': 'disableReedemEnrollmentBtn'
}, },
initialize: function (options) { initialize: function (options) {
...@@ -33,18 +32,6 @@ define([ ...@@ -33,18 +32,6 @@ define([
this.code = options.code; this.code = options.code;
}, },
disableReedemEnrollmentBtn: function(event) {
var btn = $('.redeem-enrollment');
if (btn.attr('disabled')) {
event.preventDefault();
} else {
btn.text('Enrolling...')
.attr('disabled', true)
.removeClass('btn-success')
.addClass('btn-default');
}
},
changePage: function() { changePage: function() {
this.$el.html( this.$el.html(
this.template({ this.template({
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
// views // views
// -------------------- // --------------------
@import 'views/basket'; @import 'views/basket';
@import 'views/cancel_error';
@import 'views/credit'; @import 'views/credit';
@import 'views/course_admin'; @import 'views/course_admin';
@import 'views/coupon_admin'; @import 'views/coupon_admin';
......
.receipt-cancel-error {
font-family: $font-family-sans-serif;
h1 {
font-weight: 600;
margin-bottom: 30px;
text-align: center;
}
.nav-link {
border-bottom: none;
text-decoration: none !important;
&:active, &:hover, &:focus {
border-bottom: 1px dotted #0079bc;
}
}
p {
font-size: large;
}
}
\ No newline at end of file
...@@ -310,8 +310,4 @@ ...@@ -310,8 +310,4 @@
color: #6B6969; color: #6B6969;
} }
.btn-default[disabled]:hover,
.btn-default[disabled]:focus {
color: #333;
}
} }
...@@ -70,7 +70,8 @@ ...@@ -70,7 +70,8 @@
<% } else { %> <% } else { %>
<% if (isEnrollmentCode) { %> <% if (isEnrollmentCode) { %>
<a href="/coupons/redeem/?code=<%= code %>&sku=<%= course.attributes.stockrecords.partner_sku %>" <a href="/coupons/redeem/?code=<%= code %>&sku=<%= course.attributes.stockrecords.partner_sku %>"
class="btn btn-success redeem-enrollment"><%- gettext('Enroll Now') %></a> id="RedeemEnrollment"
class="btn btn-success"><%- gettext('Enroll Now') %></a>
<% } else { %> <% } else { %>
<a href="/coupons/redeem/?code=<%= code %>&sku=<%= course.attributes.stockrecords.partner_sku %>" <a href="/coupons/redeem/?code=<%= code %>&sku=<%= course.attributes.stockrecords.partner_sku %>"
id="PurchaseCertificate" id="PurchaseCertificate"
......
...@@ -4,27 +4,23 @@ ...@@ -4,27 +4,23 @@
{% block title %} {% block title %}
{% trans "Checkout Error" %} {% trans "Checkout Error" %}
{% endblock %} {% endblock title %}
{% block navbar %} {% block navbar %}
{% include 'edx/partials/_student_navbar.html' %} {% include 'edx/partials/_student_navbar.html' %}
{% endblock %} {% endblock navbar %}
{% block content %} {% block content %}
<div id="error-message"> <div class="container content-wrapper receipt-cancel-error">
<div class="container"> <h1>{% trans "Checkout Error" %}</h1>
<div class="depth depth-2 message-error-content"> <p>{% blocktrans %} An error has occurred with your payment. <b>You have not been charged.</b>
<h1>{% trans "Checkout Error" %}</h1> {% endblocktrans %}</p>
<h3>{{ error }}</h3>
<p>{% blocktrans %} An error has occurred with your payment. <b>You have not been charged.</b> <p>{% with "<a class='nav-link' href='mailto:"|add:payment_support_email|add:"'>"|safe as start_link %}
{% endblocktrans %}</p> {% blocktrans with end_link="</a>"|safe %}
<p>{% with "<a class='nav-link' href='mailto:"|add:payment_support_email|add:"'>"|safe as start_link %} Please try to submit your payment again. If this problem persists, contact {{ start_link }}
{% blocktrans with end_link="</a>"|safe %} {{ payment_support_email }}{{ end_link }}.
Please try to submit your payment again. If this problem persists, contact {{ start_link }} {% endblocktrans %}
{{ payment_support_email }}{{ end_link }}. {% endwith %}</p>
{% endblocktrans %}
{% endwith %}</p>
</div>
</div>
</div> </div>
{% endblock %} {% endblock content %}
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