Commit 47cd0f3e by asadiqbal08

EX-81 / Ex-84 changes

parent 7225420f
...@@ -9,6 +9,7 @@ from django.utils.translation import ugettext as _ ...@@ -9,6 +9,7 @@ from django.utils.translation import ugettext as _
from util.json_request import JsonResponse from util.json_request import JsonResponse
from django.http import HttpResponse, HttpResponseNotFound from django.http import HttpResponse, HttpResponseNotFound
from shoppingcart.models import Coupon, CourseRegistrationCode from shoppingcart.models import Coupon, CourseRegistrationCode
from opaque_keys.edx.locations import SlashSeparatedCourseKey
import logging import logging
...@@ -54,32 +55,34 @@ def add_coupon(request, course_id): # pylint: disable=W0613 ...@@ -54,32 +55,34 @@ def add_coupon(request, course_id): # pylint: disable=W0613
code = request.POST.get('code') code = request.POST.get('code')
# check if the code is already in the Coupons Table and active # check if the code is already in the Coupons Table and active
coupon = Coupon.objects.filter(is_active=True, code=code) try:
course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id)
if coupon: coupon = Coupon.objects.get(is_active=True, code=code, course_id=course_id)
return HttpResponseNotFound(_("coupon with the coupon code ({code}) already exist").format(code=code)) except Coupon.DoesNotExist:
# check if the coupon code is in the CourseRegistrationCode Table
# check if the coupon code is in the CourseRegistrationCode Table course_registration_code = CourseRegistrationCode.objects.filter(code=code)
course_registration_code = CourseRegistrationCode.objects.filter(code=code) if course_registration_code:
if course_registration_code: return HttpResponseNotFound(_(
return HttpResponseNotFound(_( "The code ({code}) that you have tried to define is already in use as a registration code").format(code=code)
"The code ({code}) that you have tried to define is already in use as a registration code").format(code=code) )
description = request.POST.get('description')
course_id = request.POST.get('course_id')
try:
discount = int(request.POST.get('discount'))
except ValueError:
return HttpResponseNotFound(_("Please Enter the Integer Value for Coupon Discount"))
if discount > 100 or discount < 0:
return HttpResponseNotFound(_("Please Enter the Coupon Discount Value Less than or Equal to 100"))
coupon = Coupon(
code=code, description=description, course_id=course_id,
percentage_discount=discount, created_by_id=request.user.id
) )
coupon.save()
return HttpResponse(_("coupon with the coupon code ({code}) added successfully").format(code=code))
description = request.POST.get('description') if coupon:
course_id = request.POST.get('course_id') return HttpResponseNotFound(_("coupon with the coupon code ({code}) already exists for this course").format(code=code))
try:
discount = int(request.POST.get('discount'))
except ValueError:
return HttpResponseNotFound(_("Please Enter the Integer Value for Coupon Discount"))
if discount > 100:
return HttpResponseNotFound(_("Please Enter the Coupon Discount Value Less than or Equal to 100"))
coupon = Coupon(
code=code, description=description, course_id=course_id,
percentage_discount=discount, created_by_id=request.user.id
)
coupon.save()
return HttpResponse(_("coupon with the coupon code ({code}) added successfully").format(code=code))
@require_POST @require_POST
......
...@@ -81,7 +81,7 @@ def purchase_transactions(course_id, features): ...@@ -81,7 +81,7 @@ def purchase_transactions(course_id, features):
] ]
""" """
purchased_courses = PaidCourseRegistration.objects.filter(course_id=course_id, status='purchased') purchased_courses = PaidCourseRegistration.objects.filter(course_id=course_id, status='purchased').order_by('user')
def purchase_transactions_info(purchased_course, features): def purchase_transactions_info(purchased_course, features):
""" convert purchase transactions to dictionary """ """ convert purchase transactions to dictionary """
...@@ -103,12 +103,17 @@ def purchase_transactions(course_id, features): ...@@ -103,12 +103,17 @@ def purchase_transactions(course_id, features):
for feature in order_item_features) for feature in order_item_features)
order_item_dict.update({"orderitem_id": getattr(purchased_course, 'id')}) order_item_dict.update({"orderitem_id": getattr(purchased_course, 'id')})
try: coupon_redemption = CouponRedemption.objects.select_related('coupon').filter(order_id=purchased_course.order_id)
coupon_redemption = CouponRedemption.objects.select_related('coupon').get(order_id=purchased_course.order_id) if coupon_redemption:
except CouponRedemption.DoesNotExist: # we format the coupon codes in comma separated way if there are more then one coupon against a order id.
coupon_code_dict = {'coupon_code': 'None'} coupon_codes = list()
for redemption in coupon_redemption:
coupon_codes.append(redemption.coupon.code)
coupon_code_dict = {'coupon_code': ", ".join(coupon_codes)}
else: else:
coupon_code_dict = {'coupon_code': coupon_redemption.coupon.code} coupon_code_dict = {'coupon_code': 'None'}
student_dict.update(dict(order_dict.items() + order_item_dict.items() + coupon_code_dict.items())) student_dict.update(dict(order_dict.items() + order_item_dict.items() + coupon_code_dict.items()))
student_dict.update({'course_id': course_id.to_deprecated_string()}) student_dict.update({'course_id': course_id.to_deprecated_string()})
......
...@@ -32,11 +32,7 @@ class CouponDoesNotExistException(InvalidCartItem): ...@@ -32,11 +32,7 @@ class CouponDoesNotExistException(InvalidCartItem):
pass pass
class CouponAlreadyExistException(InvalidCartItem): class MultipleCouponsNotAllowedException(InvalidCartItem):
pass
class ItemDoesNotExistAgainstCouponException(InvalidCartItem):
pass pass
......
...@@ -32,8 +32,7 @@ from verify_student.models import SoftwareSecurePhotoVerification ...@@ -32,8 +32,7 @@ from verify_student.models import SoftwareSecurePhotoVerification
from .exceptions import (InvalidCartItem, PurchasedCallbackException, ItemAlreadyInCartException, from .exceptions import (InvalidCartItem, PurchasedCallbackException, ItemAlreadyInCartException,
AlreadyEnrolledInCourseException, CourseDoesNotExistException, AlreadyEnrolledInCourseException, CourseDoesNotExistException,
CouponAlreadyExistException, ItemDoesNotExistAgainstCouponException, MultipleCouponsNotAllowedException, RegCodeAlreadyExistException, ItemDoesNotExistAgainstRegCodeException)
RegCodeAlreadyExistException, ItemDoesNotExistAgainstRegCodeException)
from microsite_configuration import microsite from microsite_configuration import microsite
...@@ -498,31 +497,33 @@ class CouponRedemption(models.Model): ...@@ -498,31 +497,33 @@ class CouponRedemption(models.Model):
return value - discount return value - discount
@classmethod @classmethod
def add_coupon_redemption(cls, coupon, order): def add_coupon_redemption(cls, coupon, order, cart_items):
""" """
add coupon info into coupon_redemption model add coupon info into coupon_redemption model
""" """
cart_items = order.orderitem_set.all().select_subclasses() is_redemption_applied = False
coupon_redemptions = cls.objects.filter(order=order, user=order.user)
for coupon_redemption in coupon_redemptions:
if coupon_redemption.coupon.code != coupon.code or coupon_redemption.coupon.id == coupon.id:
log.exception("Coupon redemption already exist for user '{0}' against order id '{1}'"
.format(order.user.username, order.id))
raise MultipleCouponsNotAllowedException
for item in cart_items: for item in cart_items:
if getattr(item, 'course_id'): if getattr(item, 'course_id'):
if item.course_id == coupon.course_id: if item.course_id == coupon.course_id:
coupon_redemption, created = cls.objects.get_or_create(order=order, user=order.user, coupon=coupon) coupon_redemption = cls(order=order, user=order.user, coupon=coupon)
if not created: coupon_redemption.save()
log.exception("Coupon '{0}' already exist for user '{1}' against order id '{2}'"
.format(coupon.code, order.user.username, order.id))
raise CouponAlreadyExistException
discount_price = cls.get_discount_price(coupon.percentage_discount, item.unit_cost) discount_price = cls.get_discount_price(coupon.percentage_discount, item.unit_cost)
item.list_price = item.unit_cost item.list_price = item.unit_cost
item.unit_cost = discount_price item.unit_cost = discount_price
item.save() item.save()
log.info("Discount generated for user {0} against order id '{1}' " log.info("Discount generated for user {0} against order id '{1}' "
.format(order.user.username, order.id)) .format(order.user.username, order.id))
return coupon_redemption is_redemption_applied = True
return is_redemption_applied
log.warning("Course item does not exist for coupon '{0}'".format(coupon.code)) return is_redemption_applied
raise ItemDoesNotExistAgainstCouponException
class PaidCourseRegistration(OrderItem): class PaidCourseRegistration(OrderItem):
......
...@@ -77,18 +77,18 @@ class ShoppingCartViewsTests(ModuleStoreTestCase): ...@@ -77,18 +77,18 @@ class ShoppingCartViewsTests(ModuleStoreTestCase):
self.cart = Order.get_cart_for_user(self.user) self.cart = Order.get_cart_for_user(self.user)
self.addCleanup(patcher.stop) self.addCleanup(patcher.stop)
def get_discount(self): def get_discount(self, cost):
""" """
This method simple return the discounted amount This method simple return the discounted amount
""" """
val = Decimal("{0:.2f}".format(Decimal(self.percentage_discount / 100.00) * self.cost)) val = Decimal("{0:.2f}".format(Decimal(self.percentage_discount / 100.00) * cost))
return self.cost - val return cost - val
def add_coupon(self, course_key, is_active): def add_coupon(self, course_key, is_active, code):
""" """
add dummy coupon into models add dummy coupon into models
""" """
coupon = Coupon(code=self.coupon_code, description='testing code', course_id=course_key, coupon = Coupon(code=code, description='testing code', course_id=course_key,
percentage_discount=self.percentage_discount, created_by=self.user, is_active=is_active) percentage_discount=self.percentage_discount, created_by=self.user, is_active=is_active)
coupon.save() coupon.save()
...@@ -99,12 +99,12 @@ class ShoppingCartViewsTests(ModuleStoreTestCase): ...@@ -99,12 +99,12 @@ class ShoppingCartViewsTests(ModuleStoreTestCase):
course_reg_code = CourseRegistrationCode(code=self.reg_code, course_id=course_key, created_by=self.user) course_reg_code = CourseRegistrationCode(code=self.reg_code, course_id=course_key, created_by=self.user)
course_reg_code.save() course_reg_code.save()
def add_course_to_user_cart(self): def add_course_to_user_cart(self, course_key):
""" """
adding course to user cart adding course to user cart
""" """
self.login_user() self.login_user()
reg_item = PaidCourseRegistration.add_to_order(self.cart, self.course_key) reg_item = PaidCourseRegistration.add_to_order(self.cart, course_key)
return reg_item return reg_item
def login_user(self): def login_user(self):
...@@ -122,8 +122,8 @@ class ShoppingCartViewsTests(ModuleStoreTestCase): ...@@ -122,8 +122,8 @@ class ShoppingCartViewsTests(ModuleStoreTestCase):
self.assertIn('The course {0} is already in your cart.'.format(self.course_key.to_deprecated_string()), resp.content) self.assertIn('The course {0} is already in your cart.'.format(self.course_key.to_deprecated_string()), resp.content)
def test_course_discount_invalid_coupon(self): def test_course_discount_invalid_coupon(self):
self.add_coupon(self.course_key, True) self.add_coupon(self.course_key, True, self.coupon_code)
self.add_course_to_user_cart() self.add_course_to_user_cart(self.course_key)
non_existing_code = "non_existing_code" non_existing_code = "non_existing_code"
resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': non_existing_code}) resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': non_existing_code})
self.assertEqual(resp.status_code, 404) self.assertEqual(resp.status_code, 404)
...@@ -131,23 +131,23 @@ class ShoppingCartViewsTests(ModuleStoreTestCase): ...@@ -131,23 +131,23 @@ class ShoppingCartViewsTests(ModuleStoreTestCase):
def test_course_discount_invalid_reg_code(self): def test_course_discount_invalid_reg_code(self):
self.add_reg_code(self.course_key) self.add_reg_code(self.course_key)
self.add_course_to_user_cart() self.add_course_to_user_cart(self.course_key)
non_existing_code = "non_existing_code" non_existing_code = "non_existing_code"
resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': non_existing_code}) resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': non_existing_code})
self.assertEqual(resp.status_code, 404) self.assertEqual(resp.status_code, 404)
self.assertIn("Discount does not exist against code '{0}'.".format(non_existing_code), resp.content) self.assertIn("Discount does not exist against code '{0}'.".format(non_existing_code), resp.content)
def test_course_discount_inactive_coupon(self): def test_course_discount_inactive_coupon(self):
self.add_coupon(self.course_key, False) self.add_coupon(self.course_key, False, self.coupon_code)
self.add_course_to_user_cart() self.add_course_to_user_cart(self.course_key)
resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.coupon_code}) resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.coupon_code})
self.assertEqual(resp.status_code, 404) self.assertEqual(resp.status_code, 404)
self.assertIn("Discount does not exist against code '{0}'.".format(self.coupon_code), resp.content) self.assertIn("Discount does not exist against code '{0}'.".format(self.coupon_code), resp.content)
def test_course_does_not_exist_in_cart_against_valid_coupon(self): def test_course_does_not_exist_in_cart_against_valid_coupon(self):
course_key = self.course_key.to_deprecated_string() + 'testing' course_key = self.course_key.to_deprecated_string() + 'testing'
self.add_coupon(course_key, True) self.add_coupon(course_key, True, self.coupon_code)
self.add_course_to_user_cart() self.add_course_to_user_cart(self.course_key)
resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.coupon_code}) resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.coupon_code})
self.assertEqual(resp.status_code, 404) self.assertEqual(resp.status_code, 404)
...@@ -156,7 +156,7 @@ class ShoppingCartViewsTests(ModuleStoreTestCase): ...@@ -156,7 +156,7 @@ class ShoppingCartViewsTests(ModuleStoreTestCase):
def test_course_does_not_exist_in_cart_against_valid_reg_code(self): def test_course_does_not_exist_in_cart_against_valid_reg_code(self):
course_key = self.course_key.to_deprecated_string() + 'testing' course_key = self.course_key.to_deprecated_string() + 'testing'
self.add_reg_code(course_key) self.add_reg_code(course_key)
self.add_course_to_user_cart() self.add_course_to_user_cart(self.course_key)
resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.reg_code}) resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.reg_code})
self.assertEqual(resp.status_code, 404) self.assertEqual(resp.status_code, 404)
...@@ -164,26 +164,64 @@ class ShoppingCartViewsTests(ModuleStoreTestCase): ...@@ -164,26 +164,64 @@ class ShoppingCartViewsTests(ModuleStoreTestCase):
def test_course_discount_for_valid_active_coupon_code(self): def test_course_discount_for_valid_active_coupon_code(self):
self.add_coupon(self.course_key, True) self.add_coupon(self.course_key, True, self.coupon_code)
self.add_course_to_user_cart() self.add_course_to_user_cart(self.course_key)
resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.coupon_code}) resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.coupon_code})
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
# unit price should be updated for that course # unit price should be updated for that course
item = self.cart.orderitem_set.all().select_subclasses()[0] item = self.cart.orderitem_set.all().select_subclasses()[0]
self.assertEquals(item.unit_cost, self.get_discount()) self.assertEquals(item.unit_cost, self.get_discount(self.cost))
# after getting 10 percent discount # after getting 10 percent discount
self.assertEqual(self.cart.total_cost, self.get_discount()) self.assertEqual(self.cart.total_cost, self.get_discount(self.cost))
# now using the same coupon code against the same order.
# Only one coupon redemption should be allowed per order.
resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.coupon_code})
self.assertEqual(resp.status_code, 400)
self.assertIn("Only one coupon redemption is allowed against an order", resp.content)
def test_course_discount_against_two_distinct_coupon_codes(self):
self.add_coupon(self.course_key, True, self.coupon_code)
self.add_course_to_user_cart(self.course_key)
# now testing coupon code already used scenario, reusing the same coupon code
resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.coupon_code}) resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.coupon_code})
self.assertEqual(resp.status_code, 200)
# unit price should be updated for that course
item = self.cart.orderitem_set.all().select_subclasses()[0]
self.assertEquals(item.unit_cost, self.get_discount(self.cost))
# now using another valid active coupon code.
# Only one coupon redemption should be allowed per order.
self.add_coupon(self.course_key, True, 'abxyz')
resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': 'abxyz'})
self.assertEqual(resp.status_code, 400) self.assertEqual(resp.status_code, 400)
self.assertIn("Coupon '{0}' already used.".format(self.coupon_code), resp.content) self.assertIn("Only one coupon redemption is allowed against an order", resp.content)
def test_same_coupons_code_on_multiple_courses(self):
# add two same coupon codes on two different courses
self.add_coupon(self.course_key, True, self.coupon_code)
self.add_coupon(self.testing_course.id, True, self.coupon_code)
self.add_course_to_user_cart(self.course_key)
self.add_course_to_user_cart(self.testing_course.id)
resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.coupon_code})
self.assertEqual(resp.status_code, 200)
# unit price should be updated for that course
item = self.cart.orderitem_set.all().select_subclasses()[0]
self.assertEquals(item.unit_cost, self.get_discount(self.cost))
item = self.cart.orderitem_set.all().select_subclasses()[1]
self.assertEquals(item.unit_cost, self.get_discount(self.testing_cost))
def test_soft_delete_coupon(self): # pylint: disable=E1101 def test_soft_delete_coupon(self): # pylint: disable=E1101
self.add_coupon(self.course_key, True) self.add_coupon(self.course_key, True, self.coupon_code)
coupon = Coupon(code='TestCode', description='testing', course_id=self.course_key, coupon = Coupon(code='TestCode', description='testing', course_id=self.course_key,
percentage_discount=12, created_by=self.user, is_active=True) percentage_discount=12, created_by=self.user, is_active=True)
coupon.save() coupon.save()
...@@ -218,7 +256,7 @@ class ShoppingCartViewsTests(ModuleStoreTestCase): ...@@ -218,7 +256,7 @@ class ShoppingCartViewsTests(ModuleStoreTestCase):
def test_course_free_discount_for_valid_active_reg_code(self): def test_course_free_discount_for_valid_active_reg_code(self):
self.add_reg_code(self.course_key) self.add_reg_code(self.course_key)
self.add_course_to_user_cart() self.add_course_to_user_cart(self.course_key)
resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.reg_code}) resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.reg_code})
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
...@@ -236,7 +274,7 @@ class ShoppingCartViewsTests(ModuleStoreTestCase): ...@@ -236,7 +274,7 @@ class ShoppingCartViewsTests(ModuleStoreTestCase):
@patch('shoppingcart.views.log.debug') @patch('shoppingcart.views.log.debug')
def test_non_existing_coupon_redemption_on_removing_item(self, debug_log): def test_non_existing_coupon_redemption_on_removing_item(self, debug_log):
reg_item = self.add_course_to_user_cart() reg_item = self.add_course_to_user_cart(self.course_key)
resp = self.client.post(reverse('shoppingcart.views.remove_item', args=[]), resp = self.client.post(reverse('shoppingcart.views.remove_item', args=[]),
{'id': reg_item.id}) {'id': reg_item.id})
debug_log.assert_called_with( debug_log.assert_called_with(
...@@ -248,8 +286,8 @@ class ShoppingCartViewsTests(ModuleStoreTestCase): ...@@ -248,8 +286,8 @@ class ShoppingCartViewsTests(ModuleStoreTestCase):
@patch('shoppingcart.views.log.info') @patch('shoppingcart.views.log.info')
def test_existing_coupon_redemption_on_removing_item(self, info_log): def test_existing_coupon_redemption_on_removing_item(self, info_log):
self.add_coupon(self.course_key, True) self.add_coupon(self.course_key, True, self.coupon_code)
reg_item = self.add_course_to_user_cart() reg_item = self.add_course_to_user_cart(self.course_key)
resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.coupon_code}) resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.coupon_code})
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
...@@ -266,7 +304,7 @@ class ShoppingCartViewsTests(ModuleStoreTestCase): ...@@ -266,7 +304,7 @@ class ShoppingCartViewsTests(ModuleStoreTestCase):
def test_existing_reg_code_redemption_on_removing_item(self, info_log): def test_existing_reg_code_redemption_on_removing_item(self, info_log):
self.add_reg_code(self.course_key) self.add_reg_code(self.course_key)
reg_item = self.add_course_to_user_cart() reg_item = self.add_course_to_user_cart(self.course_key)
resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.reg_code}) resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.reg_code})
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
...@@ -282,8 +320,8 @@ class ShoppingCartViewsTests(ModuleStoreTestCase): ...@@ -282,8 +320,8 @@ class ShoppingCartViewsTests(ModuleStoreTestCase):
@patch('shoppingcart.views.log.info') @patch('shoppingcart.views.log.info')
def test_coupon_discount_for_multiple_courses_in_cart(self, info_log): def test_coupon_discount_for_multiple_courses_in_cart(self, info_log):
reg_item = self.add_course_to_user_cart() reg_item = self.add_course_to_user_cart(self.course_key)
self.add_coupon(self.course_key, True) self.add_coupon(self.course_key, True, self.coupon_code)
cert_item = CertificateItem.add_to_order(self.cart, self.verified_course_key, self.cost, 'honor') cert_item = CertificateItem.add_to_order(self.cart, self.verified_course_key, self.cost, 'honor')
self.assertEquals(self.cart.orderitem_set.count(), 2) self.assertEquals(self.cart.orderitem_set.count(), 2)
...@@ -294,7 +332,7 @@ class ShoppingCartViewsTests(ModuleStoreTestCase): ...@@ -294,7 +332,7 @@ class ShoppingCartViewsTests(ModuleStoreTestCase):
items = self.cart.orderitem_set.all().select_subclasses() items = self.cart.orderitem_set.all().select_subclasses()
for item in items: for item in items:
if item.id == reg_item.id: if item.id == reg_item.id:
self.assertEquals(item.unit_cost, self.get_discount()) self.assertEquals(item.unit_cost, self.get_discount(self.cost))
elif item.id == cert_item.id: elif item.id == cert_item.id:
self.assertEquals(item.list_price, None) self.assertEquals(item.list_price, None)
...@@ -310,7 +348,7 @@ class ShoppingCartViewsTests(ModuleStoreTestCase): ...@@ -310,7 +348,7 @@ class ShoppingCartViewsTests(ModuleStoreTestCase):
@patch('shoppingcart.views.log.info') @patch('shoppingcart.views.log.info')
def test_reg_code_free_discount_with_multiple_courses_in_cart(self, info_log): def test_reg_code_free_discount_with_multiple_courses_in_cart(self, info_log):
reg_item = self.add_course_to_user_cart() reg_item = self.add_course_to_user_cart(self.course_key)
self.add_reg_code(self.course_key) self.add_reg_code(self.course_key)
cert_item = CertificateItem.add_to_order(self.cart, self.verified_course_key, self.cost, 'honor') cert_item = CertificateItem.add_to_order(self.cart, self.verified_course_key, self.cost, 'honor')
self.assertEquals(self.cart.orderitem_set.count(), 2) self.assertEquals(self.cart.orderitem_set.count(), 2)
...@@ -338,7 +376,7 @@ class ShoppingCartViewsTests(ModuleStoreTestCase): ...@@ -338,7 +376,7 @@ class ShoppingCartViewsTests(ModuleStoreTestCase):
@patch('shoppingcart.views.log.info') @patch('shoppingcart.views.log.info')
def test_delete_certificate_item(self, info_log): def test_delete_certificate_item(self, info_log):
reg_item = self.add_course_to_user_cart() self.add_course_to_user_cart(self.course_key)
cert_item = CertificateItem.add_to_order(self.cart, self.verified_course_key, self.cost, 'honor') cert_item = CertificateItem.add_to_order(self.cart, self.verified_course_key, self.cost, 'honor')
self.assertEquals(self.cart.orderitem_set.count(), 2) self.assertEquals(self.cart.orderitem_set.count(), 2)
...@@ -354,11 +392,11 @@ class ShoppingCartViewsTests(ModuleStoreTestCase): ...@@ -354,11 +392,11 @@ class ShoppingCartViewsTests(ModuleStoreTestCase):
@patch('shoppingcart.views.log.info') @patch('shoppingcart.views.log.info')
def test_remove_coupon_redemption_on_clear_cart(self, info_log): def test_remove_coupon_redemption_on_clear_cart(self, info_log):
reg_item = self.add_course_to_user_cart() reg_item = self.add_course_to_user_cart(self.course_key)
CertificateItem.add_to_order(self.cart, self.verified_course_key, self.cost, 'honor') CertificateItem.add_to_order(self.cart, self.verified_course_key, self.cost, 'honor')
self.assertEquals(self.cart.orderitem_set.count(), 2) self.assertEquals(self.cart.orderitem_set.count(), 2)
self.add_coupon(self.course_key, True) self.add_coupon(self.course_key, True, self.coupon_code)
resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.coupon_code}) resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.coupon_code})
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
...@@ -372,7 +410,7 @@ class ShoppingCartViewsTests(ModuleStoreTestCase): ...@@ -372,7 +410,7 @@ class ShoppingCartViewsTests(ModuleStoreTestCase):
@patch('shoppingcart.views.log.info') @patch('shoppingcart.views.log.info')
def test_remove_registration_code_redemption_on_clear_cart(self, info_log): def test_remove_registration_code_redemption_on_clear_cart(self, info_log):
reg_item = self.add_course_to_user_cart() reg_item = self.add_course_to_user_cart(self.course_key)
CertificateItem.add_to_order(self.cart, self.verified_course_key, self.cost, 'honor') CertificateItem.add_to_order(self.cart, self.verified_course_key, self.cost, 'honor')
self.assertEquals(self.cart.orderitem_set.count(), 2) self.assertEquals(self.cart.orderitem_set.count(), 2)
...@@ -504,9 +542,9 @@ class ShoppingCartViewsTests(ModuleStoreTestCase): ...@@ -504,9 +542,9 @@ class ShoppingCartViewsTests(ModuleStoreTestCase):
self.assertEqual(resp2.status_code, 404) self.assertEqual(resp2.status_code, 404)
def test_total_amount_of_purchased_course(self): def test_total_amount_of_purchased_course(self):
self.add_course_to_user_cart() self.add_course_to_user_cart(self.course_key)
self.assertEquals(self.cart.orderitem_set.count(), 1) self.assertEquals(self.cart.orderitem_set.count(), 1)
self.add_coupon(self.course_key, True) self.add_coupon(self.course_key, True, self.coupon_code)
resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.coupon_code}) resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.coupon_code})
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
...@@ -526,8 +564,8 @@ class ShoppingCartViewsTests(ModuleStoreTestCase): ...@@ -526,8 +564,8 @@ class ShoppingCartViewsTests(ModuleStoreTestCase):
@patch('shoppingcart.views.render_to_response', render_mock) @patch('shoppingcart.views.render_to_response', render_mock)
def test_show_receipt_success_with_valid_coupon_code(self): def test_show_receipt_success_with_valid_coupon_code(self):
self.add_course_to_user_cart() self.add_course_to_user_cart(self.course_key)
self.add_coupon(self.course_key, True) self.add_coupon(self.course_key, True, self.coupon_code)
resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.coupon_code}) resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.coupon_code})
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
...@@ -536,14 +574,14 @@ class ShoppingCartViewsTests(ModuleStoreTestCase): ...@@ -536,14 +574,14 @@ class ShoppingCartViewsTests(ModuleStoreTestCase):
resp = self.client.get(reverse('shoppingcart.views.show_receipt', args=[self.cart.id])) resp = self.client.get(reverse('shoppingcart.views.show_receipt', args=[self.cart.id]))
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
self.assertIn('FirstNameTesting123', resp.content) self.assertIn('FirstNameTesting123', resp.content)
self.assertIn(str(self.get_discount()), resp.content) self.assertIn(str(self.get_discount(self.cost)), resp.content)
@patch('shoppingcart.views.render_to_response', render_mock) @patch('shoppingcart.views.render_to_response', render_mock)
def test_reg_code_and_course_registration_scenario(self): def test_reg_code_and_course_registration_scenario(self):
self.add_reg_code(self.course_key) self.add_reg_code(self.course_key)
# One courses in user shopping cart # One courses in user shopping cart
self.add_course_to_user_cart() self.add_course_to_user_cart(self.course_key)
self.assertEquals(self.cart.orderitem_set.count(), 1) self.assertEquals(self.cart.orderitem_set.count(), 1)
resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.reg_code}) resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.reg_code})
...@@ -585,7 +623,7 @@ class ShoppingCartViewsTests(ModuleStoreTestCase): ...@@ -585,7 +623,7 @@ class ShoppingCartViewsTests(ModuleStoreTestCase):
@patch('shoppingcart.views.render_to_response', render_mock) @patch('shoppingcart.views.render_to_response', render_mock)
def test_show_receipt_success_with_valid_reg_code(self): def test_show_receipt_success_with_valid_reg_code(self):
self.add_course_to_user_cart() self.add_course_to_user_cart(self.course_key)
self.add_reg_code(self.course_key) self.add_reg_code(self.course_key)
resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.reg_code}) resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.reg_code})
......
...@@ -15,7 +15,8 @@ from opaque_keys.edx.locations import SlashSeparatedCourseKey ...@@ -15,7 +15,8 @@ from opaque_keys.edx.locations import SlashSeparatedCourseKey
from shoppingcart.reports import RefundReport, ItemizedPurchaseReport, UniversityRevenueShareReport, CertificateStatusReport from shoppingcart.reports import RefundReport, ItemizedPurchaseReport, UniversityRevenueShareReport, CertificateStatusReport
from student.models import CourseEnrollment from student.models import CourseEnrollment
from .exceptions import ItemAlreadyInCartException, AlreadyEnrolledInCourseException, CourseDoesNotExistException, ReportTypeDoesNotExistException, \ from .exceptions import ItemAlreadyInCartException, AlreadyEnrolledInCourseException, CourseDoesNotExistException, ReportTypeDoesNotExistException, \
CouponAlreadyExistException, ItemDoesNotExistAgainstCouponException, RegCodeAlreadyExistException, ItemDoesNotExistAgainstRegCodeException RegCodeAlreadyExistException, ItemDoesNotExistAgainstRegCodeException,\
MultipleCouponsNotAllowedException
from .models import Order, PaidCourseRegistration, OrderItem, Coupon, CouponRedemption, CourseRegistrationCode, RegistrationCodeRedemption from .models import Order, PaidCourseRegistration, OrderItem, Coupon, CouponRedemption, CourseRegistrationCode, RegistrationCodeRedemption
from .processors import process_postpay_callback, render_purchase_form_html from .processors import process_postpay_callback, render_purchase_form_html
import json import json
...@@ -154,9 +155,8 @@ def use_code(request): ...@@ -154,9 +155,8 @@ def use_code(request):
Valid Code can be either coupon or registration code. Valid Code can be either coupon or registration code.
""" """
code = request.POST["code"] code = request.POST["code"]
try: coupons = Coupon.objects.filter(code=code, is_active=True)
coupon = Coupon.objects.get(code=code, is_active=True) if not coupons:
except Coupon.DoesNotExist:
# If not coupon code then we check that code against course registration code # If not coupon code then we check that code against course registration code
try: try:
course_reg = CourseRegistrationCode.objects.get(code=code) course_reg = CourseRegistrationCode.objects.get(code=code)
...@@ -165,7 +165,7 @@ def use_code(request): ...@@ -165,7 +165,7 @@ def use_code(request):
return use_registration_code(course_reg, request.user) return use_registration_code(course_reg, request.user)
return use_coupon_code(coupon, request.user) return use_coupon_code(coupons, request.user)
def use_registration_code(course_reg, user): def use_registration_code(course_reg, user):
...@@ -183,17 +183,23 @@ def use_registration_code(course_reg, user): ...@@ -183,17 +183,23 @@ def use_registration_code(course_reg, user):
return HttpResponse(json.dumps({'response': 'success'}), content_type="application/json") return HttpResponse(json.dumps({'response': 'success'}), content_type="application/json")
def use_coupon_code(coupon, user): def use_coupon_code(coupons, user):
""" """
This method utilize course coupon code This method utilize course coupon code
""" """
try: cart = Order.get_cart_for_user(user)
cart = Order.get_cart_for_user(user) cart_items = cart.orderitem_set.all().select_subclasses()
CouponRedemption.add_coupon_redemption(coupon, cart) is_redemption_applied = False
except CouponAlreadyExistException: for coupon in coupons:
return HttpResponseBadRequest(_("Coupon '{0}' already used.".format(coupon.code))) try:
except ItemDoesNotExistAgainstCouponException: if CouponRedemption.add_coupon_redemption(coupon, cart, cart_items):
return HttpResponseNotFound(_("Coupon '{0}' is not valid for any course in the shopping cart.".format(coupon.code))) is_redemption_applied = True
except MultipleCouponsNotAllowedException:
return HttpResponseBadRequest(_("Only one coupon redemption is allowed against an order"))
if not is_redemption_applied:
log.warning("Course item does not exist for coupon '{0}'".format(coupons[0].code))
return HttpResponseNotFound(_("Coupon '{0}' is not valid for any course in the shopping cart.".format(coupons[0].code)))
return HttpResponse(json.dumps({'response': 'success'}), content_type="application/json") return HttpResponse(json.dumps({'response': 'success'}), content_type="application/json")
......
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