Commit 59c7da23 by Renzo Lucioni

Update Course model to allow creation of multiple credit seats

Courses may have multiple credit seats associated with them. To make this possible, the query used to locate existing seats has been extended to include credit provider in the query. Our SKU generation utility has also been modified to include the credit provider in the hash. XCOM-574.
parent 8866134c
...@@ -138,8 +138,24 @@ class Course(models.Model): ...@@ -138,8 +138,24 @@ class Course(models.Model):
attribute_values__value_boolean=id_verification_required attribute_values__value_boolean=id_verification_required
) )
if credit_provider is None:
# Yields a match if attribute names do not include 'credit_provider'.
credit_provider_query = ~Q(attributes__name='credit_provider')
else:
# Yields a match if attribute with name 'credit_provider' matches provided value.
credit_provider_query = Q(
attributes__name='credit_provider',
attribute_values__value_text=credit_provider
)
try: try:
seat = self.seat_products.filter(certificate_type_query).get(id_verification_required_query) seat = self.seat_products.filter(
certificate_type_query
).filter(
id_verification_required_query
).get(
credit_provider_query
)
logger.info( logger.info(
'Retrieved course seat child product with certificate type [%s] for [%s] from database.', 'Retrieved course seat child product with certificate type [%s] for [%s] from database.',
......
...@@ -107,31 +107,56 @@ class CourseTests(CourseCatalogTestMixin, TestCase): ...@@ -107,31 +107,56 @@ class CourseTests(CourseCatalogTestMixin, TestCase):
""" Verify the method creates or updates a seat Product. """ """ Verify the method creates or updates a seat Product. """
course = Course.objects.create(id='a/b/c', name='Test Course') course = Course.objects.create(id='a/b/c', name='Test Course')
# Test creation # Test seat creation
certificate_type = 'honor' certificate_type = 'verified'
id_verification_required = True id_verification_required = True
price = 0 price = 5
course.create_or_update_seat(certificate_type, id_verification_required, price) course.create_or_update_seat(certificate_type, id_verification_required, price)
# Two seats: one honor, the other the parent seat product # Two seats: one verified, the other the parent seat product
self.assertEqual(course.products.count(), 2) self.assertEqual(course.products.count(), 2)
seat = course.seat_products[0] seat = course.seat_products[0]
self.assert_course_seat_valid(seat, course, certificate_type, id_verification_required, price) self.assert_course_seat_valid(seat, course, certificate_type, id_verification_required, price)
# Test update # Test seat update
price = 100 price = 10
credit_provider = 'MIT' course.create_or_update_seat(certificate_type, id_verification_required, price)
credit_hours = 2
course.create_or_update_seat(
certificate_type, id_verification_required, price, credit_provider, credit_hours=credit_hours
)
# Again, only two seats with one being the parent seat product. # Again, only two seats with one being the parent seat product.
self.assertEqual(course.products.count(), 2) self.assertEqual(course.products.count(), 2)
seat = course.seat_products[0] seat = course.seat_products[0]
self.assert_course_seat_valid( self.assert_course_seat_valid(seat, course, certificate_type, id_verification_required, price)
seat, course, certificate_type, id_verification_required, price, credit_provider, credit_hours=credit_hours
) def test_create_credit_seats(self):
"""Verify that the model's seat creation method allows the creation of multiple credit seats."""
course = Course.objects.create(id='a/b/c', name='Test Course')
credit_data = {'MIT': 2, 'Harvard': 0.5}
certificate_type = 'credit'
id_verification_required = True
price = 10
# Verify that the course can have multiple credit seats added to it
for credit_provider, credit_hours in credit_data.iteritems():
credit_seat = course.create_or_update_seat(
certificate_type,
id_verification_required,
price,
credit_provider=credit_provider,
credit_hours=credit_hours
)
self.assert_course_seat_valid(
credit_seat,
course,
certificate_type,
id_verification_required,
price,
credit_provider=credit_provider,
credit_hours=credit_hours
)
# Expected seat total, with one being the parent seat product.
self.assertEqual(course.products.count(), len(credit_data) + 1)
def test_collision_avoidance(self): def test_collision_avoidance(self):
""" """
......
...@@ -15,7 +15,8 @@ class UtilsTests(CourseCatalogTestMixin, TestCase): ...@@ -15,7 +15,8 @@ class UtilsTests(CourseCatalogTestMixin, TestCase):
certificate_type = 'honor' certificate_type = 'honor'
product = course.create_or_update_seat(certificate_type, False, 0) product = course.create_or_update_seat(certificate_type, False, 0)
_hash = md5(u'{} {} {}'.format(certificate_type, course_id, 'False')).hexdigest()[-7:] _hash = u'{} {} {} {}'.format(certificate_type, course_id, 'False', '')
_hash = md5(_hash.lower()).hexdigest()[-7:]
expected = _hash.upper() expected = _hash.upper()
actual = generate_sku(product) actual = generate_sku(product)
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
...@@ -10,11 +10,12 @@ def generate_sku(product): ...@@ -10,11 +10,12 @@ def generate_sku(product):
# Note: This currently supports seats. In the future, this should # Note: This currently supports seats. In the future, this should
# be updated to accommodate other product classes. # be updated to accommodate other product classes.
_hash = u' '.join(( _hash = u' '.join((
getattr(product.attr, 'certificate_type', '').lower(), getattr(product.attr, 'certificate_type', ''),
product.attr.course_key.lower(), product.attr.course_key,
unicode(product.attr.id_verification_required) unicode(product.attr.id_verification_required),
getattr(product.attr, 'credit_provider', '')
)) ))
_hash = md5(_hash) _hash = md5(_hash.lower())
_hash = _hash.hexdigest()[-7:] _hash = _hash.hexdigest()[-7:]
return _hash.upper() return _hash.upper()
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