Commit 91a47962 by chrisndodge

Merge pull request #6196 from edx/muhhshoaib/WL-168

WL-168 When redeeming a Registration Code in the shopping cart, the user should be redirect to the Registration Code Redemption page
parents 4589a976 5a437b39
......@@ -289,9 +289,15 @@ class DashboardTest(ModuleStoreTestCase):
resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': course_reg_code.code})
self.assertEqual(resp.status_code, 200)
# freely enroll the user into course
resp = self.client.get(reverse('shoppingcart.views.register_courses'))
self.assertIn('success', resp.content)
redeem_url = reverse('register_code_redemption', args=[course_reg_code.code])
response = self.client.get(redeem_url)
self.assertEquals(response.status_code, 200)
# check button text
self.assertTrue('Activate Course Enrollment' in response.content)
#now activate the user by enrolling him/her to the course
response = self.client.post(redeem_url)
self.assertEquals(response.status_code, 200)
response = self.client.get(reverse('dashboard'))
self.assertIn('You can no longer access this course because payment has not yet been received', response.content)
......
......@@ -1862,30 +1862,6 @@ class TestInstructorAPILevelsDataDump(ModuleStoreTestCase, LoginEnrollmentTestCa
for res in res_json['sale']:
self.validate_sale_records_response(res, course_registration_code, self.sale_invoice_1, 0)
def test_get_sale_records_features_with_used_code(self):
"""
Test that the response from get_sale_records is in json format and using one of the registration codes.
"""
for i in range(5):
course_registration_code = CourseRegistrationCode(
code='qwerty{}'.format(i), course_id=self.course.id.to_deprecated_string(),
created_by=self.instructor, invoice=self.sale_invoice_1
)
course_registration_code.save()
PaidCourseRegistration.add_to_order(self.cart, self.course.id)
# now using registration code
self.client.post(reverse('shoppingcart.views.use_code'), {'code': 'qwerty0'})
url = reverse('get_sale_records', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {})
res_json = json.loads(response.content)
self.assertIn('sale', res_json)
for res in res_json['sale']:
self.validate_sale_records_response(res, course_registration_code, self.sale_invoice_1, 1)
def test_get_sale_records_features_with_multiple_invoices(self):
"""
Test that the response from get_sale_records is in json format for multiple invoices
......@@ -3038,7 +3014,8 @@ class TestCourseRegistrationCodes(ModuleStoreTestCase):
for i in range(5):
i += 1
registration_code_redemption = RegistrationCodeRedemption(
order_id=i, registration_code_id=i, redeemed_by=self.instructor
registration_code_id=i,
redeemed_by=self.instructor
)
registration_code_redemption.save()
......@@ -3220,7 +3197,8 @@ class TestCourseRegistrationCodes(ModuleStoreTestCase):
for i in range(9):
i += 13
registration_code_redemption = RegistrationCodeRedemption(
order_id=i, registration_code_id=i, redeemed_by=self.instructor
registration_code_id=i,
redeemed_by=self.instructor
)
registration_code_redemption.save()
......
......@@ -798,8 +798,6 @@ def get_sale_order_records(request, course_id): # pylint: disable=unused-argume
('company_contact_name', 'Company Contact Name'),
('company_contact_email', 'Company Contact Email'),
('total_amount', 'Total Amount'),
('total_codes', 'Total Codes'),
('total_used_codes', 'Total Used Codes'),
('logged_in_username', 'Login Username'),
('logged_in_email', 'Login User Email'),
('purchase_time', 'Date of Sale'),
......@@ -817,8 +815,6 @@ def get_sale_order_records(request, course_id): # pylint: disable=unused-argume
('coupon_code', 'Coupon Code'),
('unit_cost', 'Unit Price'),
('list_price', 'List Price'),
('codes', 'Registration Codes'),
('course_id', 'Course Id')
]
db_columns = [x[0] for x in query_features]
......@@ -1156,7 +1152,7 @@ def generate_registration_codes(request, course_id):
generated_registration_code = save_registration_code(request.user, course_id, sale_invoice, order=None)
registration_codes.append(generated_registration_code)
site_name = microsite.get_value('SITE_NAME', 'localhost')
site_name = microsite.get_value('SITE_NAME', settings.SITE_NAME)
course = get_course_by_id(course_id, depth=None)
course_honor_mode = CourseMode.mode_for_course(course_id, 'honor')
course_price = course_honor_mode.min_price
......
......@@ -60,7 +60,6 @@ def sale_order_record_features(course_id, features):
"""
sale_order_features = [x for x in SALE_ORDER_FEATURES if x in features]
course_reg_features = [x for x in COURSE_REGISTRATION_FEATURES if x in features]
order_item_features = [x for x in ORDER_ITEM_FEATURES if x in features]
# Extracting order information
......@@ -74,9 +73,6 @@ def sale_order_record_features(course_id, features):
sale_order_dict.update({"logged_in_username": purchased_course.order.user.username})
sale_order_dict.update({"logged_in_email": purchased_course.order.user.email})
sale_order_dict.update({"total_codes": 'N/A'})
sale_order_dict.update({'total_used_codes': 'N/A'})
# Extracting OrderItem information of unit_cost, list_price and status
order_item_dict = dict((feature, getattr(purchased_course, feature, None))
for feature in order_item_features)
......@@ -89,22 +85,6 @@ def sale_order_record_features(course_id, features):
order_item_dict.update({'coupon_code': ", ".join(coupon_codes)})
sale_order_dict.update(dict(order_item_dict.items()))
if getattr(purchased_course.order, 'order_type') == OrderTypes.BUSINESS:
registration_codes = CourseRegistrationCode.objects.filter(order=purchased_course.order, course_id=course_id)
sale_order_dict.update({"total_codes": registration_codes.count()})
total_used_codes = RegistrationCodeRedemption.objects.filter(registration_code__in=registration_codes).count()
sale_order_dict.update({'total_used_codes': total_used_codes})
codes = [reg_code.code for reg_code in registration_codes]
# Extracting registration code information
obj_course_reg_code = registration_codes.all()[:1].get()
course_reg_dict = dict((feature, getattr(obj_course_reg_code, feature))
for feature in course_reg_features)
course_reg_dict['course_id'] = course_id.to_deprecated_string()
course_reg_dict.update({'codes': ", ".join(codes)})
sale_order_dict.update(dict(course_reg_dict.items()))
return sale_order_dict
......
......@@ -238,8 +238,6 @@ class TestCourseSaleRecordsAnalyticsBasic(ModuleStoreTestCase):
self.assertEqual(sale_order_record['company_contact_name'], order.company_contact_name)
self.assertEqual(sale_order_record['company_contact_email'], order.company_contact_email)
self.assertEqual(sale_order_record['customer_reference_number'], order.customer_reference_number)
self.assertEqual(sale_order_record['total_used_codes'], order.registrationcoderedemption_set.all().count())
self.assertEqual(sale_order_record['total_codes'], len(CourseRegistrationCode.objects.filter(order=order)))
self.assertEqual(sale_order_record['unit_cost'], item.unit_cost)
self.assertEqual(sale_order_record['list_price'], item.list_price)
self.assertEqual(sale_order_record['status'], item.status)
......@@ -281,7 +279,7 @@ class TestCourseRegistrationCodeAnalyticsBasic(ModuleStoreTestCase):
order.save()
registration_code_redemption = RegistrationCodeRedemption(
order=order, registration_code_id=1, redeemed_by=self.instructor
registration_code_id=1, redeemed_by=self.instructor
)
registration_code_redemption.save()
registration_codes = CourseRegistrationCode.objects.all()
......
......@@ -37,18 +37,6 @@ class MultipleCouponsNotAllowedException(InvalidCartItem):
pass
class RegCodeAlreadyExistException(InvalidCartItem):
pass
class ItemNotAllowedToRedeemRegCodeException(InvalidCartItem):
pass
class ItemDoesNotExistAgainstRegCodeException(InvalidCartItem):
pass
class ReportException(Exception):
pass
......@@ -63,3 +51,7 @@ class InvalidStatusToRetire(Exception):
class UnexpectedOrderItemStatus(Exception):
pass
class ItemNotFoundInCartException(Exception):
pass
......@@ -44,11 +44,9 @@ from .exceptions import (
AlreadyEnrolledInCourseException,
CourseDoesNotExistException,
MultipleCouponsNotAllowedException,
RegCodeAlreadyExistException,
ItemDoesNotExistAgainstRegCodeException,
ItemNotAllowedToRedeemRegCodeException,
InvalidStatusToRetire,
UnexpectedOrderItemStatus,
ItemNotFoundInCartException
)
from microsite_configuration import microsite
......@@ -552,6 +550,23 @@ class Order(models.Model):
for item in self.orderitem_set.all(): # pylint: disable=no-member
item.retire()
def find_item_by_course_id(self, course_id):
"""
course_id: Course id of the item to find
Returns OrderItem from the Order given a course_id
Raises exception ItemNotFoundException when the item
having the given course_id is not present in the cart
"""
cart_items = OrderItem.objects.filter(order=self).select_subclasses()
found_items = []
for item in cart_items:
if getattr(item, 'course_id', None):
if item.course_id == course_id:
found_items.append(item)
if not found_items:
raise ItemNotFoundInCartException
return found_items
class OrderItem(TimeStampedModel):
"""
......@@ -730,25 +745,6 @@ class CourseRegistrationCode(models.Model):
order = models.ForeignKey(Order, db_index=True, null=True, related_name="purchase_order")
invoice = models.ForeignKey(Invoice, null=True)
@classmethod
@transaction.commit_on_success
def free_user_enrollment(cls, cart):
"""
Here we enroll the user free for all courses available in shopping cart
"""
cart_items = cart.orderitem_set.all().select_subclasses()
if cart_items:
for item in cart_items:
CourseEnrollment.enroll(cart.user, item.course_id)
log.info("Enrolled '{0}' in free course '{1}'"
.format(cart.user.email, item.course_id)) # pylint: disable=no-member
item.status = 'purchased'
item.save()
cart.status = 'purchased'
cart.purchase_time = datetime.now(pytz.utc)
cart.save()
class RegistrationCodeRedemption(models.Model):
"""
......@@ -761,47 +757,12 @@ class RegistrationCodeRedemption(models.Model):
course_enrollment = models.ForeignKey(CourseEnrollment, null=True)
@classmethod
def delete_registration_redemption(cls, user, cart):
def is_registration_code_redeemed(cls, course_reg_code):
"""
This method delete registration redemption
Checks the existence of the registration code
in the RegistrationCodeRedemption
"""
reg_code_redemption = cls.objects.filter(redeemed_by=user, order=cart)
if reg_code_redemption:
reg_code_redemption.delete()
log.info('Registration code redemption entry removed for user {0} for order {1}'.format(user, cart.id))
@classmethod
def add_reg_code_redemption(cls, course_reg_code, order):
"""
add course registration code info into RegistrationCodeRedemption model
"""
cart_items = order.orderitem_set.all().select_subclasses()
for item in cart_items:
if getattr(item, 'course_id'):
if item.course_id == course_reg_code.course_id:
# If the item qty is greater than 1 then the registration code should not be allowed to
# redeem
if item.qty > 1:
raise ItemNotAllowedToRedeemRegCodeException
# If another account tries to use a existing registration code before the student checks out, an
# error message will appear.The reg code is un-reusable.
code_redemption = cls.objects.filter(registration_code=course_reg_code)
if code_redemption:
log.exception("Registration code '{0}' already used".format(course_reg_code.code))
raise RegCodeAlreadyExistException
code_redemption = RegistrationCodeRedemption(registration_code=course_reg_code, order=order, redeemed_by=order.user)
code_redemption.save()
item.list_price = item.unit_cost
item.unit_cost = 0
item.save()
log.info("Code '{0}' is used by user {1} against order id '{2}' "
.format(course_reg_code.code, order.user.username, order.id))
return course_reg_code
log.warning("Course item does not exist against registration code '{0}'".format(course_reg_code.code))
raise ItemDoesNotExistAgainstRegCodeException
return cls.objects.filter(registration_code=course_reg_code).exists()
@classmethod
def create_invoice_generated_registration_redemption(cls, course_reg_code, user):
......
......@@ -17,7 +17,6 @@ urlpatterns = patterns('shoppingcart.views', # nopep8
url(r'^reset_code_redemption/$', 'reset_code_redemption'),
url(r'^billing_details/$', 'billing_details', name='billing_details'),
url(r'^verify_cart/$', 'verify_cart'),
url(r'^register_courses/$', 'register_courses'),
)
if settings.FEATURES.get('ENABLE_PAYMENT_FAKE'):
......
......@@ -117,6 +117,14 @@ var edx = edx || {};
$(document).ready(function() {
// (click on the payment submit button).
$('.cart-view form input[type="submit"]').click(function(event) {
// check if there is code exists in the inout_code field
// before going to make payment
// if exists then trigger click event of the apply code button
var code = $('div.code-input input#input_code').val();
if (typeof(code) != 'undefined' && code != ''){
$('div.code-input #submit-code').trigger('click');
return false;
}
var container = $('.confirm-enrollment.cart-view form');
var view = new edx.shoppingcart.showcart.CartView({
el:container
......
......@@ -236,7 +236,6 @@
}
a.course-link-bg-color {
background-color: #00A1E5;
background-image: linear-gradient(#00A1E5, #00A1E5);
border: 16px solid #00A1E5;
box-shadow: 0 1px 0 0 #00A1E5 inset;
text-shadow: 0 1px 0 #00A1E5;
......@@ -254,6 +253,11 @@
text-decoration: none;
font-size: 24px;
text-align: center;
&:hover {
background: $m-blue-d2;
border: 16px solid $m-blue-d2;
box-shadow: 0 1px 0 0 $m-blue-d2 inset;
}
}
input[type="submit"] {
text-transform: none;
......@@ -272,6 +276,10 @@
text-decoration: none;
text-shadow: 0 1px 0 #00A1E5;
font-size: 24px;
&:hover {
background: $m-blue-d2;
box-shadow: none;
}
}
}
......
......@@ -65,8 +65,8 @@ from courseware.courses import course_image_url, get_course_about_section
</div>
% if not reg_code_already_redeemed:
%if redemption_success:
<% course_url = reverse('info', args=[course.id.to_deprecated_string()]) %>
<a href="${course_url}" class="link-button course-link-bg-color">${_("View Course &nbsp; &nbsp; &#x25b8;")}</a>
<% dashboard_url = reverse('dashboard') %>
<a href="${dashboard_url}" class="link-button course-link-bg-color">${_("View Dashboard &nbsp; &nbsp; &#x25b8;")}</a>
%elif not registered_for_course:
<form method="post">
<input type="hidden" name="csrfmiddlewaretoken" value="${ csrf_token }">
......
......@@ -100,9 +100,7 @@ from django.utils.translation import ugettext as _
</div>
<div class="col-two">
<div class="col-2 relative">
% if amount == 0:
<input type="submit" value = "Register" id="register" >
% elif order_type == 'business':
% if order_type == 'business':
<div name="billing">
<input type="submit" value = "Billing Details" name="billing-details"><i class="icon-caret-right"></i>
<p>
......@@ -172,8 +170,14 @@ from django.utils.translation import ugettext as _
}
)
.success(function(data) {
location.reload(true);
})
if (data.coupon_code_applied) {
location.reload(true); // Reload the page if the coupon code was applied.
}
else {
// Redirect to the redemption URL if the Registration code was applied.
location.href = data.redemption_url;
}
})
.error(function(data,status) {
if(status=="parsererror"){
location.reload(true);
......@@ -199,23 +203,15 @@ from django.utils.translation import ugettext as _
})
});
$('#register').click(function(event){
event.preventDefault();
var post_url = "${reverse('shoppingcart.views.register_courses')}";
$.post(post_url)
.success(function(data) {
window.location.href = "${reverse('dashboard')}";
})
.error(function(data,status) {
if(status=="parsererror"){
location.reload(true);
}else{
showErrorMsgs(data.responseText)
}
})
});
$("input[name='billing-details']").click(function(event){
// check if there is code exists in the inout_code field
// before going to billing details page
// if exists then trigger click event of the apply code button
var code = $('div.code-input input#input_code').val();
if (code!= ''){
$('div.code-input #submit-code').trigger('click');
return false;
}
event.preventDefault();
location.href = "${reverse('shoppingcart.views.billing_details')}";
});
......
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