From fdfda81addb9bd7f67a0907ce0e94a2695d964cb Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Mon, 1 Jun 2015 14:00:52 -0400 Subject: [PATCH] don't assume in the ORM query a single RegCodeRedemption per enrollment record Removed the unused try/except block around filter(). --- lms/djangoapps/shoppingcart/models.py | 13 +++-- .../shoppingcart/tests/test_models.py | 57 ++++++++++++++++++- 2 files changed, 65 insertions(+), 5 deletions(-) diff --git a/lms/djangoapps/shoppingcart/models.py b/lms/djangoapps/shoppingcart/models.py index b462d268c7..8bf707890d 100644 --- a/lms/djangoapps/shoppingcart/models.py +++ b/lms/djangoapps/shoppingcart/models.py @@ -1185,10 +1185,15 @@ class RegistrationCodeRedemption(models.Model): Returns RegistrationCodeRedemption object if registration code has been used during the course enrollment else Returns None. """ - try: - return cls.objects.get(course_enrollment=course_enrollment) - except RegistrationCodeRedemption.DoesNotExist: - return None + # theoretically there could be more than one (e.g. someone self-unenrolls + # then re-enrolls with a different regcode) + reg_codes = cls.objects.filter(course_enrollment=course_enrollment).order_by('-redeemed_at') + if reg_codes: + # return the first one. In all normal use cases of registration codes + # the user will only have one + return reg_codes[0] + + return None @classmethod def is_registration_code_redeemed(cls, course_reg_code): diff --git a/lms/djangoapps/shoppingcart/tests/test_models.py b/lms/djangoapps/shoppingcart/tests/test_models.py index b3581e0832..447e9bf29f 100644 --- a/lms/djangoapps/shoppingcart/tests/test_models.py +++ b/lms/djangoapps/shoppingcart/tests/test_models.py @@ -27,7 +27,8 @@ from shoppingcart.models import ( Order, OrderItem, CertificateItem, InvalidCartItem, CourseRegistrationCode, PaidCourseRegistration, CourseRegCodeItem, Donation, OrderItemSubclassPK, - Invoice, CourseRegistrationCodeInvoiceItem, InvoiceTransaction, InvoiceHistory + Invoice, CourseRegistrationCodeInvoiceItem, InvoiceTransaction, InvoiceHistory, + RegistrationCodeRedemption ) from student.tests.factories import UserFactory from student.models import CourseEnrollment @@ -470,6 +471,60 @@ class PaidCourseRegistrationTest(ModuleStoreTestCase): # check that the registration codes are generated against the order self.assertEqual(len(CourseRegistrationCode.objects.filter(order=self.cart)), item.qty) + def test_regcode_redemptions(self): + """ + Asserts the data model around RegistrationCodeRedemption + """ + self.cart.order_type = 'business' + self.cart.save() + CourseRegCodeItem.add_to_order(self.cart, self.course_key, 2) + self.cart.purchase() + + reg_code = CourseRegistrationCode.objects.filter(order=self.cart)[0] + + enrollment = CourseEnrollment.enroll(self.user, self.course_key) + + redemption = RegistrationCodeRedemption( + registration_code=reg_code, + redeemed_by=self.user, + course_enrollment=enrollment + ) + redemption.save() + + test_redemption = RegistrationCodeRedemption.registration_code_used_for_enrollment(enrollment) + + self.assertEqual(test_redemption.id, redemption.id) # pylint: disable=no-member + + def test_regcode_multi_redemptions(self): + """ + Asserts the data model around RegistrationCodeRedemption and + what happens when we do multiple redemptions by same user + """ + self.cart.order_type = 'business' + self.cart.save() + CourseRegCodeItem.add_to_order(self.cart, self.course_key, 2) + self.cart.purchase() + + reg_codes = CourseRegistrationCode.objects.filter(order=self.cart) + + self.assertEqual(len(reg_codes), 2) + + enrollment = CourseEnrollment.enroll(self.user, self.course_key) + + ids = [] + for reg_code in reg_codes: + redemption = RegistrationCodeRedemption( + registration_code=reg_code, + redeemed_by=self.user, + course_enrollment=enrollment + ) + redemption.save() + ids.append(redemption.id) # pylint: disable=no-member + + test_redemption = RegistrationCodeRedemption.registration_code_used_for_enrollment(enrollment) + + self.assertIn(test_redemption.id, ids) # pylint: disable=no-member + def test_add_with_default_mode(self): """ Tests add_to_cart where the mode specified in the argument is NOT in the database