Commit 829f7dba by Muhammad Shoaib

Remove items from the shopping cart if they are for a course whose course…

Remove items from the shopping cart if they are for a course whose course enrollment window has closed

changed the url name to verify_cart and change the color of the message in the shopping cart
parent 699b3d08
...@@ -770,6 +770,17 @@ class CourseEnrollment(models.Model): ...@@ -770,6 +770,17 @@ class CourseEnrollment(models.Model):
return enrollment_number return enrollment_number
@classmethod @classmethod
def is_enrollment_closed(cls, user, course):
"""
Returns a boolean value regarding whether the user has access to enroll in the course. Returns False if the
enrollment has been closed.
"""
# Disable the pylint error here, as per ormsbee. This local import was previously
# in CourseEnrollment.enroll
from courseware.access import has_access # pylint: disable=import-error
return not has_access(user, 'enroll', course)
@classmethod
def is_course_full(cls, course): def is_course_full(cls, course):
""" """
Returns a boolean value regarding whether a course has already reached it's max enrollment Returns a boolean value regarding whether a course has already reached it's max enrollment
...@@ -904,8 +915,6 @@ class CourseEnrollment(models.Model): ...@@ -904,8 +915,6 @@ class CourseEnrollment(models.Model):
Also emits relevant events for analytics purposes. Also emits relevant events for analytics purposes.
""" """
from courseware.access import has_access
# All the server-side checks for whether a user is allowed to enroll. # All the server-side checks for whether a user is allowed to enroll.
try: try:
course = modulestore().get_course(course_key) course = modulestore().get_course(course_key)
...@@ -921,7 +930,7 @@ class CourseEnrollment(models.Model): ...@@ -921,7 +930,7 @@ class CourseEnrollment(models.Model):
if check_access: if check_access:
if course is None: if course is None:
raise NonExistentCourseError raise NonExistentCourseError
if not has_access(user, 'enroll', course): if CourseEnrollment.is_enrollment_closed(user, course):
log.warning( log.warning(
"User {0} failed to enroll in course {1} because enrollment is closed".format( "User {0} failed to enroll in course {1} because enrollment is closed".format(
user.username, user.username,
......
...@@ -152,6 +152,15 @@ class Order(models.Model): ...@@ -152,6 +152,15 @@ class Order(models.Model):
return False return False
@classmethod
def remove_cart_item_from_order(cls, item):
"""
Removes the item from the cart if the item.order.status == 'cart'.
"""
if item.order.status == 'cart':
log.info("Item {0} removed from the user cart".format(item.id))
item.delete()
@property @property
def total_cost(self): def total_cost(self):
""" """
......
""" """
Tests for Shopping Cart views Tests for Shopping Cart views
""" """
import pytz
from urlparse import urlparse from urlparse import urlparse
from django.http import HttpRequest from django.http import HttpRequest
...@@ -1104,6 +1105,120 @@ class ShoppingCartViewsTests(ModuleStoreTestCase): ...@@ -1104,6 +1105,120 @@ class ShoppingCartViewsTests(ModuleStoreTestCase):
@override_settings(MODULESTORE=MODULESTORE_CONFIG) @override_settings(MODULESTORE=MODULESTORE_CONFIG)
@patch.dict('django.conf.settings.FEATURES', {'ENABLE_PAID_COURSE_REGISTRATION': True}) @patch.dict('django.conf.settings.FEATURES', {'ENABLE_PAID_COURSE_REGISTRATION': True})
class ShoppingcartViewsClosedEnrollment(ModuleStoreTestCase):
"""
Test suite for ShoppingcartViews Course Enrollments Closed or not
"""
def setUp(self):
super(ShoppingcartViewsClosedEnrollment, self).setUp()
self.user = UserFactory.create()
self.user.set_password('password')
self.user.save()
self.instructor = AdminFactory.create()
self.cost = 40
self.course = CourseFactory.create(org='MITx', number='999', display_name='Robot Super Course')
self.course_key = self.course.id
self.course_mode = CourseMode(course_id=self.course_key,
mode_slug="honor",
mode_display_name="honor cert",
min_price=self.cost)
self.course_mode.save()
self.testing_course = CourseFactory.create(
org='Edx',
number='999',
display_name='Testing Super Course',
metadata={"invitation_only": False}
)
self.course_mode = CourseMode(course_id=self.testing_course.id,
mode_slug="honor",
mode_display_name="honor cert",
min_price=self.cost)
self.course_mode.save()
self.cart = Order.get_cart_for_user(self.user)
self.now = datetime.now(pytz.UTC)
self.tomorrow = self.now + timedelta(days=1)
self.nextday = self.tomorrow + timedelta(days=1)
def login_user(self):
"""
Helper fn to login self.user
"""
self.client.login(username=self.user.username, password="password")
@patch('shoppingcart.views.render_to_response', render_mock)
def test_to_check_that_cart_item_enrollment_is_closed(self):
self.login_user()
reg_item1 = PaidCourseRegistration.add_to_order(self.cart, self.course_key)
PaidCourseRegistration.add_to_order(self.cart, self.testing_course.id)
# update the testing_course enrollment dates
self.testing_course.enrollment_start = self.tomorrow
self.testing_course.enrollment_end = self.nextday
self.testing_course = self.update_course(self.testing_course, self.user.id)
# testing_course enrollment is closed but the course is in the cart
# so we delete that item from the cart and display the message in the cart
resp = self.client.get(reverse('shoppingcart.views.show_cart', args=[]))
self.assertEqual(resp.status_code, 200)
self.assertIn("{course_name} has been removed because the enrollment period has closed.".format(course_name=self.testing_course.display_name), resp.content)
((template, context), _tmp) = render_mock.call_args
self.assertEqual(template, 'shoppingcart/shopping_cart.html')
self.assertEqual(context['order'], self.cart)
self.assertIn(reg_item1, context['shoppingcart_items'][0])
self.assertEqual(1, len(context['shoppingcart_items']))
self.assertEqual(True, context['is_course_enrollment_closed'])
self.assertIn(self.testing_course.display_name, context['appended_expired_course_names'])
def test_to_check_that_cart_item_enrollment_is_closed_when_clicking_the_payment_button(self):
self.login_user()
PaidCourseRegistration.add_to_order(self.cart, self.course_key)
PaidCourseRegistration.add_to_order(self.cart, self.testing_course.id)
# update the testing_course enrollment dates
self.testing_course.enrollment_start = self.tomorrow
self.testing_course.enrollment_end = self.nextday
self.testing_course = self.update_course(self.testing_course, self.user.id)
# testing_course enrollment is closed but the course is in the cart
# so we delete that item from the cart and display the message in the cart
resp = self.client.get(reverse('shoppingcart.views.verify_cart'))
self.assertEqual(resp.status_code, 200)
self.assertTrue(json.loads(resp.content)['is_course_enrollment_closed'])
resp = self.client.get(reverse('shoppingcart.views.show_cart', args=[]))
self.assertEqual(resp.status_code, 200)
self.assertIn("{course_name} has been removed because the enrollment period has closed.".format(course_name=self.testing_course.display_name), resp.content)
self.assertIn('40.00', resp.content)
def test_is_enrollment_closed_when_order_type_is_business(self):
self.login_user()
self.cart.order_type = 'business'
self.cart.save()
PaidCourseRegistration.add_to_order(self.cart, self.course_key)
CourseRegCodeItem.add_to_order(self.cart, self.testing_course.id, 2)
# update the testing_course enrollment dates
self.testing_course.enrollment_start = self.tomorrow
self.testing_course.enrollment_end = self.nextday
self.testing_course = self.update_course(self.testing_course, self.user.id)
resp = self.client.post(reverse('shoppingcart.views.billing_details'))
self.assertEqual(resp.status_code, 200)
self.assertTrue(json.loads(resp.content)['is_course_enrollment_closed'])
# testing_course enrollment is closed but the course is in the cart
# so we delete that item from the cart and display the message in the cart
resp = self.client.get(reverse('shoppingcart.views.show_cart', args=[]))
self.assertEqual(resp.status_code, 200)
self.assertIn("{course_name} has been removed because the enrollment period has closed.".format(course_name=self.testing_course.display_name), resp.content)
self.assertIn('40.00', resp.content)
@override_settings(MODULESTORE=MODULESTORE_CONFIG)
@patch.dict('django.conf.settings.FEATURES', {'ENABLE_PAID_COURSE_REGISTRATION': True})
class RegistrationCodeRedemptionCourseEnrollment(ModuleStoreTestCase): class RegistrationCodeRedemptionCourseEnrollment(ModuleStoreTestCase):
""" """
Test suite for RegistrationCodeRedemption Course Enrollments Test suite for RegistrationCodeRedemption Course Enrollments
......
...@@ -16,6 +16,7 @@ urlpatterns = patterns('shoppingcart.views', # nopep8 ...@@ -16,6 +16,7 @@ urlpatterns = patterns('shoppingcart.views', # nopep8
url(r'^update_user_cart/$', 'update_user_cart'), url(r'^update_user_cart/$', 'update_user_cart'),
url(r'^reset_code_redemption/$', 'reset_code_redemption'), url(r'^reset_code_redemption/$', 'reset_code_redemption'),
url(r'^billing_details/$', 'billing_details', name='billing_details'), url(r'^billing_details/$', 'billing_details', name='billing_details'),
url(r'^verify_cart/$', 'verify_cart'),
url(r'^register_courses/$', 'register_courses'), url(r'^register_courses/$', 'register_courses'),
) )
......
...@@ -148,25 +148,27 @@ def show_cart(request): ...@@ -148,25 +148,27 @@ def show_cart(request):
This view shows cart items. This view shows cart items.
""" """
cart = Order.get_cart_for_user(request.user) cart = Order.get_cart_for_user(request.user)
total_cost = cart.total_cost is_any_course_expired, expired_cart_items, expired_cart_item_names, valid_cart_item_tuples = \
cart_items = cart.orderitem_set.all().select_subclasses() verify_for_closed_enrollment(request.user, cart)
shoppingcart_items = []
for cart_item in cart_items:
course_key = getattr(cart_item, 'course_id')
if course_key:
course = get_course_by_id(course_key, depth=0)
shoppingcart_items.append((cart_item, course))
site_name = microsite.get_value('SITE_NAME', settings.SITE_NAME) site_name = microsite.get_value('SITE_NAME', settings.SITE_NAME)
if is_any_course_expired:
for expired_item in expired_cart_items:
Order.remove_cart_item_from_order(expired_item)
cart.update_order_type()
appended_expired_course_names = ", ".join(expired_cart_item_names)
callback_url = request.build_absolute_uri( callback_url = request.build_absolute_uri(
reverse("shoppingcart.views.postpay_callback") reverse("shoppingcart.views.postpay_callback")
) )
form_html = render_purchase_form_html(cart, callback_url=callback_url) form_html = render_purchase_form_html(cart, callback_url=callback_url)
context = { context = {
'order': cart, 'order': cart,
'shoppingcart_items': shoppingcart_items, 'shoppingcart_items': valid_cart_item_tuples,
'amount': total_cost, 'amount': cart.total_cost,
'is_course_enrollment_closed': is_any_course_expired,
'appended_expired_course_names': appended_expired_course_names,
'site_name': site_name, 'site_name': site_name,
'form_html': form_html, 'form_html': form_html,
'currency_symbol': settings.PAID_COURSE_REGISTRATION_CURRENCY[1], 'currency_symbol': settings.PAID_COURSE_REGISTRATION_CURRENCY[1],
...@@ -559,8 +561,7 @@ def billing_details(request): ...@@ -559,8 +561,7 @@ def billing_details(request):
""" """
cart = Order.get_cart_for_user(request.user) cart = Order.get_cart_for_user(request.user)
cart_items = cart.orderitem_set.all() cart_items = cart.orderitem_set.all().select_subclasses()
if getattr(cart, 'order_type') != OrderTypes.BUSINESS: if getattr(cart, 'order_type') != OrderTypes.BUSINESS:
raise Http404('Page not found!') raise Http404('Page not found!')
...@@ -589,11 +590,65 @@ def billing_details(request): ...@@ -589,11 +590,65 @@ def billing_details(request):
cart.add_billing_details(company_name, company_contact_name, company_contact_email, recipient_name, cart.add_billing_details(company_name, company_contact_name, company_contact_email, recipient_name,
recipient_email, customer_reference_number) recipient_email, customer_reference_number)
is_any_course_expired, __, __, __ = verify_for_closed_enrollment(request.user)
return JsonResponse({ return JsonResponse({
'response': _('success') 'response': _('success'),
'is_course_enrollment_closed': is_any_course_expired
}) # status code 200: OK by default }) # status code 200: OK by default
def verify_for_closed_enrollment(user, cart=None):
"""
A multi-output helper function.
inputs:
user: a user object
cart: If a cart is provided it uses the same object, otherwise fetches the user's cart.
Returns:
is_any_course_expired: True if any of the items in the cart has it's enrollment period closed. False otherwise.
expired_cart_items: List of courses with enrollment period closed.
expired_cart_item_names: List of names of the courses with enrollment period closed.
valid_cart_item_tuples: List of courses which are still open for enrollment.
"""
if cart is None:
cart = Order.get_cart_for_user(user)
expired_cart_items = []
expired_cart_item_names = []
valid_cart_item_tuples = []
cart_items = cart.orderitem_set.all().select_subclasses()
is_any_course_expired = False
for cart_item in cart_items:
course_key = getattr(cart_item, 'course_id', None)
if course_key is not None:
course = get_course_by_id(course_key, depth=0)
if CourseEnrollment.is_enrollment_closed(user, course):
is_any_course_expired = True
expired_cart_items.append(cart_item)
expired_cart_item_names.append(course.display_name)
else:
valid_cart_item_tuples.append((cart_item, course))
return is_any_course_expired, expired_cart_items, expired_cart_item_names, valid_cart_item_tuples
@require_http_methods(["GET"])
@login_required
@enforce_shopping_cart_enabled
def verify_cart(request):
"""
Called when the user clicks the button to transfer control to CyberSource.
Returns a JSON response with is_course_enrollment_closed set to True if any of the courses has its
enrollment period closed. If all courses are still valid, is_course_enrollment_closed set to False.
"""
is_any_course_expired, __, __, __ = verify_for_closed_enrollment(request.user)
return JsonResponse(
{
'is_course_enrollment_closed': is_any_course_expired
}
) # status code 200: OK by default
@login_required @login_required
def show_receipt(request, ordernum): def show_receipt(request, ordernum):
""" """
......
var edx = edx || {};
(function($) {
'use strict';
edx.shoppingcart = edx.shoppingcart || {};
edx.shoppingcart.showcart = {};
/**
* View for making shoppingcart
* @constructor
* @param {Object} params
* @param {Object} params.el - The payment form element.
*/
edx.shoppingcart.showcart.CartView = function(params) {
/**
* cart view that checks that all the cart items are valid (course enrollment is closed or not)
* before the form submitted to the payment processor.
* @param {Object} form - The form to modify.
*/
/**
* Check for all the cart items are still valid (courses enrollment are not closed)
*
* @returns {Object} The promise from the AJAX call to the server,
* which checks for cart items are valid or not and returns the boolean
* { is_course_enrollment_closed: <boolead> }
*/
var isCourseEnrollmentAllowed = function() {
return $.ajax({
url: "/shoppingcart/verify_cart/",
type: "GET"
});
};
var view = {
/**
* Initialize the view.
*
* @param {Object} params
* @param {JQuery selector} params.el - The payment form element.
* @returns {CartView}
*/
initialize: function(params) {
this.$el = params.el;
_.bindAll(view,
'submit', 'responseFromServer',
'submitPaymentForm', 'errorFromServer'
);
return this;
},
/**
* Handle a click event on the "payment form submit" button.
* This will contact the LMS server to check for all the
* valid cart items (courses enrollment should not be closed at this point)
* then send the user to the external payment processor or redirects to the
* dashboard page
*
* @param {Object} event - The click event.
*/
submit: function(event) {
// Prevent form submission
if (event) {
event.preventDefault();
}
// Immediately disable the submit button to prevent duplicate submissions
this.$el.find('input[type="submit"]').addClass("disabled");
this.$paymentForm = this.$el;
isCourseEnrollmentAllowed()
.done(this.responseFromServer)
.fail(this.errorFromServer);
return this;
},
/**
* Send signed payment parameters to the external
* payment processor if cart items are valid else redirect to
* shoppingcart.
*
* @param {boolean} data.is_course_enrollment_closed
*/
responseFromServer: function(data) {
if (data.is_course_enrollment_closed == true) {
location.href = "/shoppingcart";
}
else {
this.submitPaymentForm(this.$paymentForm);
}
},
/**
* In case the server responded back with errors
*
*/
errorFromServer: function() {
// Immediately enable the submit button to allow submission
this.$el.find('input[type="submit"]').removeClass("disabled");
},
/**
* Submit the payment from to the external payment processor.
*
* @param {Object} form
*/
submitPaymentForm: function(form) {
form.submit();
}
};
view.initialize(params);
return view;
};
$(document).ready(function() {
// (click on the payment submit button).
$('.cart-view form input[type="submit"]').click(function(event) {
var container = $('.confirm-enrollment.cart-view form');
var view = new edx.shoppingcart.showcart.CartView({
el:container
}).submit(event);
});
});
})(jQuery);
\ No newline at end of file
...@@ -261,6 +261,10 @@ ...@@ -261,6 +261,10 @@
exports: 'js/dashboard/donation', exports: 'js/dashboard/donation',
deps: ['jquery', 'underscore', 'gettext'] deps: ['jquery', 'underscore', 'gettext']
}, },
'js/shoppingcart/shoppingcart.js': {
exports: 'js/shoppingcart/shoppingcart',
deps: ['jquery', 'underscore', 'gettext']
},
// Backbone classes loaded explicitly until they are converted to use RequireJS // Backbone classes loaded explicitly until they are converted to use RequireJS
'js/models/cohort': { 'js/models/cohort': {
...@@ -382,6 +386,7 @@ ...@@ -382,6 +386,7 @@
'lms/include/js/spec/staff_debug_actions_spec.js', 'lms/include/js/spec/staff_debug_actions_spec.js',
'lms/include/js/spec/views/notification_spec.js', 'lms/include/js/spec/views/notification_spec.js',
'lms/include/js/spec/dashboard/donation.js', 'lms/include/js/spec/dashboard/donation.js',
'lms/include/js/spec/shoppingcart/shoppingcart_spec.js',
'lms/include/js/spec/student_account/account_spec.js', 'lms/include/js/spec/student_account/account_spec.js',
'lms/include/js/spec/student_account/access_spec.js', 'lms/include/js/spec/student_account/access_spec.js',
'lms/include/js/spec/student_account/login_spec.js', 'lms/include/js/spec/student_account/login_spec.js',
......
define(['js/common_helpers/ajax_helpers', 'js/shoppingcart/shoppingcart'],
function(AjaxHelpers) {
'use strict';
describe("edx.shoppingcart.showcart.CartView", function() {
var view = null;
var requests = null;
beforeEach(function() {
setFixtures('<section class="wrapper confirm-enrollment shopping-cart cart-view"><form action="" method="post"><input type="hidden" name="" value="" /><i class="icon-caret-right"></i><input type="submit" value="Payment"/></form></section>');
view = new edx.shoppingcart.showcart.CartView({
el: $('.confirm-enrollment.cart-view form')
});
spyOn(view, 'responseFromServer').andCallFake(function() {});
// Spy on AJAX requests
requests = AjaxHelpers.requests(this);
view.submit();
// Verify that the client contacts the server to
// check for all th valid cart items
AjaxHelpers.expectRequest(
requests, "GET", "/shoppingcart/verify_cart/"
);
});
it("cart has invalid items, course enrollment has been closed", function() {
// Simulate a response from the server containing the
// parameter 'is_course_enrollment_closed'. This decides that
// do we have all the cart items valid in the cart or not
AjaxHelpers.respondWithJson(requests, {
is_course_enrollment_closed: true
});
expect(view.responseFromServer).toHaveBeenCalled();
var data = view.responseFromServer.mostRecentCall.args[0]
expect(data.is_course_enrollment_closed).toBe(true);
});
it("cart has all valid items, course enrollment is still open", function() {
// Simulate a response from the server containing the
// parameter 'is_course_enrollment_closed'. This decides that
// do we have all the cart items valid in the cart or not
AjaxHelpers.respondWithJson(requests, {
is_course_enrollment_closed: false
});
expect(view.responseFromServer).toHaveBeenCalled();
var data = view.responseFromServer.mostRecentCall.args[0]
expect(data.is_course_enrollment_closed).toBe(false);
});
});
}
);
\ No newline at end of file
...@@ -171,6 +171,15 @@ ...@@ -171,6 +171,15 @@
} }
} }
} }
#expiry-msg {
padding: 15px;
background-color: #f2f2f2;
margin-top: 3px;
font-family: $sans-serif;
font-size: 14px;
text-shadow: 0px 1px 1px #fff;
border-top: 1px solid #f0f0f0;
}
.confirm-enrollment { .confirm-enrollment {
.title { .title {
font-size:24px; font-size:24px;
...@@ -885,6 +894,14 @@ ...@@ -885,6 +894,14 @@
text-align: center; text-align: center;
margin-top: 20px; margin-top: 20px;
text-transform: initial; text-transform: initial;
margin-bottom: 5px;
}
p {
font-size: 14px;
font-family: $sans-serif;
color: #9d9d9d;
text-align: center;
text-shadow: 0px 1px 1px #fff;
} }
a.blue{ a.blue{
display: inline-block; display: inline-block;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
<%block name="custom_content"> <%block name="custom_content">
<div class="container"> <div class="container">
% if shoppingcart_items: % if shoppingcart_items:
<section class="confirm-enrollment shopping-cart"> <section class="confirm-enrollment shopping-cart billing-details-view">
<h3>${_('You can proceed to payment at any point in time. Any additional information you provide will be included in your receipt.')}</h3> <h3>${_('You can proceed to payment at any point in time. Any additional information you provide will be included in your receipt.')}</h3>
<div class="billing-data"> <div class="billing-data">
<div class="col-half"> <div class="col-half">
...@@ -93,6 +93,8 @@ ...@@ -93,6 +93,8 @@
return false; return false;
} }
event.preventDefault(); event.preventDefault();
// Disable the submit button to prevent duplicate submissions
$(this).addClass("disabled");
var post_url = "${reverse('billing_details')}"; var post_url = "${reverse('billing_details')}";
var data = { var data = {
"company_name" : $('input[name="company_name"]').val(), "company_name" : $('input[name="company_name"]').val(),
...@@ -104,10 +106,15 @@ ...@@ -104,10 +106,15 @@
}; };
$.post(post_url, data) $.post(post_url, data)
.success(function(data) { .success(function(data) {
payment_form.submit(); if (data.is_course_enrollment_closed == true) {
}) location.href = "${reverse('shoppingcart.views.show_cart')}";
}
else {
payment_form.submit();
}
})
.error(function(data,status) { .error(function(data,status) {
$(this).removeClass("disabled");
}) })
}); });
}); });
......
...@@ -21,13 +21,15 @@ from django.utils.translation import ugettext as _ ...@@ -21,13 +21,15 @@ from django.utils.translation import ugettext as _
% endif % endif
</%block> </%block>
% if is_course_enrollment_closed:
<p id="expiry-msg">${_('{course_names} has been removed because the enrollment period has closed.').format(course_names=appended_expired_course_names)}</p>
% endif:
<% <%
discount_applied = False discount_applied = False
order_type = 'personal' order_type = 'personal'
%> %>
<section class="wrapper confirm-enrollment shopping-cart cart-view">
<section class="wrapper confirm-enrollment shopping-cart">
% for item, course in shoppingcart_items: % for item, course in shoppingcart_items:
% if loop.index > 0 : % if loop.index > 0 :
<hr> <hr>
...@@ -135,7 +137,10 @@ from django.utils.translation import ugettext as _ ...@@ -135,7 +137,10 @@ from django.utils.translation import ugettext as _
% else: % else:
<div class="empty-cart" > <div class="empty-cart" >
<h2>${_('Your Shopping cart is currently empty.')}</h2> <h2>${_('Your Shopping cart is currently empty.')}</h2>
<a href="${marketing_link('COURSES')}" class="blue">${_('View Courses')}</a> % if is_course_enrollment_closed:
<p>${_('{course_names} has been removed because the enrollment period has closed.').format(course_names=appended_expired_course_names)}</p>
% endif
<a href="${marketing_link('COURSES')}" class="blue">${_('View Courses')}</a>
</div> </div>
% endif % endif
...@@ -146,7 +151,7 @@ from django.utils.translation import ugettext as _ ...@@ -146,7 +151,7 @@ from django.utils.translation import ugettext as _
var isSpinnerBtnEnabled = true; var isSpinnerBtnEnabled = true;
var prevQty = 0; var prevQty = 0;
$('a.btn-remove').click(function(event) { $('a.btn-remove').click(function(event) {
event.preventDefault(); event.preventDefault();
var post_url = "${reverse('shoppingcart.views.remove_item')}"; var post_url = "${reverse('shoppingcart.views.remove_item')}";
$.post(post_url, {id:$(this).data('item-id')}) $.post(post_url, {id:$(this).data('item-id')})
......
...@@ -4,10 +4,11 @@ from django.utils.translation import ugettext as _ ...@@ -4,10 +4,11 @@ from django.utils.translation import ugettext as _
<%inherit file="../main.html" /> <%inherit file="../main.html" />
<%namespace name='static' file='/static_content.html'/> <%namespace name='static' file='/static_content.html'/>
<%block name="pagetitle">${_("Shopping cart")}</%block> <%block name="pagetitle">${_("Shopping cart")}</%block>
<%! from django.conf import settings %> <%! from django.conf import settings %>
<%! from microsite_configuration import microsite %> <%! from microsite_configuration import microsite %>
<%block name="headextra">
<script type="text/javascript" src="${static.url('js/shoppingcart/shoppingcart.js')}"></script>
</%block>
<%block name="bodyextra"> <%block name="bodyextra">
<div class="container"> <div class="container">
......
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