Commit 6badee49 by Michael Terry Committed by Michael Terry

Expect to be passed UUID

When creating course products, expect to be given the course UUID.
This way we don't have to look it up from discovery, which is the
one telling us about the products in the first place.
parent 540d1269
...@@ -18,7 +18,6 @@ from ecommerce.core.constants import (COURSE_ENTITLEMENT_PRODUCT_CLASS_NAME, COU ...@@ -18,7 +18,6 @@ from ecommerce.core.constants import (COURSE_ENTITLEMENT_PRODUCT_CLASS_NAME, COU
ISO_8601_FORMAT, SEAT_PRODUCT_CLASS_NAME) ISO_8601_FORMAT, SEAT_PRODUCT_CLASS_NAME)
from ecommerce.core.url_utils import get_ecommerce_url from ecommerce.core.url_utils import get_ecommerce_url
from ecommerce.courses.models import Course from ecommerce.courses.models import Course
from ecommerce.courses.utils import get_course_info_from_catalog
from ecommerce.entitlements.utils import create_or_update_course_entitlement from ecommerce.entitlements.utils import create_or_update_course_entitlement
from ecommerce.invoice.models import Invoice from ecommerce.invoice.models import Invoice
...@@ -399,6 +398,7 @@ class AtomicPublicationSerializer(serializers.Serializer): # pylint: disable=ab ...@@ -399,6 +398,7 @@ class AtomicPublicationSerializer(serializers.Serializer): # pylint: disable=ab
The automatically applied validation logic rejects course IDs which already exist in the database. The automatically applied validation logic rejects course IDs which already exist in the database.
""" """
id = serializers.RegexField(COURSE_ID_REGEX, max_length=255) id = serializers.RegexField(COURSE_ID_REGEX, max_length=255)
uuid = serializers.UUIDField()
name = serializers.CharField(max_length=255) name = serializers.CharField(max_length=255)
# Verification deadline should only be required if the course actually requires verification. # Verification deadline should only be required if the course actually requires verification.
verification_deadline = serializers.DateTimeField(required=False, allow_null=True) verification_deadline = serializers.DateTimeField(required=False, allow_null=True)
...@@ -441,6 +441,7 @@ class AtomicPublicationSerializer(serializers.Serializer): # pylint: disable=ab ...@@ -441,6 +441,7 @@ class AtomicPublicationSerializer(serializers.Serializer): # pylint: disable=ab
if one was raised (else None), and a message for the user, if necessary (else None). if one was raised (else None), and a message for the user, if necessary (else None).
""" """
course_id = self.validated_data['id'] course_id = self.validated_data['id']
course_uuid = self.validated_data['uuid']
course_name = self.validated_data['name'] course_name = self.validated_data['name']
course_verification_deadline = self.validated_data.get('verification_deadline') course_verification_deadline = self.validated_data.get('verification_deadline')
create_or_activate_enrollment_code = self.validated_data.get('create_or_activate_enrollment_code') create_or_activate_enrollment_code = self.validated_data.get('create_or_activate_enrollment_code')
...@@ -465,9 +466,6 @@ class AtomicPublicationSerializer(serializers.Serializer): # pylint: disable=ab ...@@ -465,9 +466,6 @@ class AtomicPublicationSerializer(serializers.Serializer): # pylint: disable=ab
course.verification_deadline = course_verification_deadline course.verification_deadline = course_verification_deadline
course.save() course.save()
# Fetch full course info (from seat product, because this queries based on attr.course_key)
course_info = get_course_info_from_catalog(course.site, course.parent_seat_product)
create_enrollment_code = False create_enrollment_code = False
if waffle.switch_is_active(ENROLLMENT_CODE_SWITCH) and site.siteconfiguration.enable_enrollment_codes: if waffle.switch_is_active(ENROLLMENT_CODE_SWITCH) and site.siteconfiguration.enable_enrollment_codes:
create_enrollment_code = create_or_activate_enrollment_code create_enrollment_code = create_or_activate_enrollment_code
...@@ -476,7 +474,7 @@ class AtomicPublicationSerializer(serializers.Serializer): # pylint: disable=ab ...@@ -476,7 +474,7 @@ class AtomicPublicationSerializer(serializers.Serializer): # pylint: disable=ab
product_class = product.get('product_class') product_class = product.get('product_class')
if product_class == COURSE_ENTITLEMENT_PRODUCT_CLASS_NAME: if product_class == COURSE_ENTITLEMENT_PRODUCT_CLASS_NAME:
EntitlementProductHelper.save(partner, course, course_info['UUID'], product) EntitlementProductHelper.save(partner, course, course_uuid, product)
elif product_class == SEAT_PRODUCT_CLASS_NAME: elif product_class == SEAT_PRODUCT_CLASS_NAME:
SeatProductHelper.save(partner, course, product, create_enrollment_code) SeatProductHelper.save(partner, course, product, create_enrollment_code)
......
...@@ -37,11 +37,13 @@ class AtomicPublicationTests(DiscoveryTestMixin, TestCase): ...@@ -37,11 +37,13 @@ class AtomicPublicationTests(DiscoveryTestMixin, TestCase):
super(AtomicPublicationTests, self).setUp() super(AtomicPublicationTests, self).setUp()
self.course_id = 'BadgerX/B101/2015' self.course_id = 'BadgerX/B101/2015'
self.course_uuid = '394a5ce5-6ff4-4b2b-bea1-a273c6920ae1'
self.course_name = 'Dances with Badgers' self.course_name = 'Dances with Badgers'
self.create_path = reverse('api:v2:publication:create') self.create_path = reverse('api:v2:publication:create')
self.update_path = reverse('api:v2:publication:update', kwargs={'course_id': self.course_id}) self.update_path = reverse('api:v2:publication:update', kwargs={'course_id': self.course_id})
self.data = { self.data = {
'id': self.course_id, 'id': self.course_id,
'uuid': self.course_uuid,
'name': self.course_name, 'name': self.course_name,
'verification_deadline': EXPIRES_STRING, 'verification_deadline': EXPIRES_STRING,
'create_or_activate_enrollment_code': False, 'create_or_activate_enrollment_code': False,
...@@ -146,14 +148,7 @@ class AtomicPublicationTests(DiscoveryTestMixin, TestCase): ...@@ -146,14 +148,7 @@ class AtomicPublicationTests(DiscoveryTestMixin, TestCase):
'name': 'certificate_type', 'name': 'certificate_type',
'value': 'verified' 'value': 'verified'
}, },
], ]
'course': {
'honor_mode': True,
'id': self.course_id,
'name': self.course_name,
'type': 'verified',
'verification_deadline': None
}
}, },
] ]
} }
...@@ -161,21 +156,8 @@ class AtomicPublicationTests(DiscoveryTestMixin, TestCase): ...@@ -161,21 +156,8 @@ class AtomicPublicationTests(DiscoveryTestMixin, TestCase):
self.user = self.create_user(is_staff=True) self.user = self.create_user(is_staff=True)
self.client.login(username=self.user.username, password=self.password) self.client.login(username=self.user.username, password=self.password)
self.get_course_info_patch = mock.patch('ecommerce.extensions.api.serializers.get_course_info_from_catalog',
AtomicPublicationTests._fake_get_course_info)
self.get_course_info_patch.start()
self.publication_switch = toggle_switch('publish_course_modes_to_lms', True) self.publication_switch = toggle_switch('publish_course_modes_to_lms', True)
def tearDown(self):
self.get_course_info_patch.stop()
@staticmethod
def _fake_get_course_info(_, product):
if product.attr.course_key == 'BadgerX/B101/2015':
return {'UUID': 'foo-bar'}
return {}
def _toggle_publication(self, is_enabled): def _toggle_publication(self, is_enabled):
"""Toggle LMS publication.""" """Toggle LMS publication."""
self.publication_switch.active = is_enabled self.publication_switch.active = is_enabled
...@@ -203,7 +185,7 @@ class AtomicPublicationTests(DiscoveryTestMixin, TestCase): ...@@ -203,7 +185,7 @@ class AtomicPublicationTests(DiscoveryTestMixin, TestCase):
attrs['certificate_type'], attrs['certificate_type'],
Decimal(product['price']), Decimal(product['price']),
self.partner, self.partner,
'foo-bar', self.course_uuid,
course.name, course.name,
) )
else: else:
...@@ -248,7 +230,7 @@ class AtomicPublicationTests(DiscoveryTestMixin, TestCase): ...@@ -248,7 +230,7 @@ class AtomicPublicationTests(DiscoveryTestMixin, TestCase):
self.assertEqual(entitlement.structure, Product.CHILD) self.assertEqual(entitlement.structure, Product.CHILD)
self.assertEqual(entitlement.parent.product_class.name, COURSE_ENTITLEMENT_PRODUCT_CLASS_NAME) self.assertEqual(entitlement.parent.product_class.name, COURSE_ENTITLEMENT_PRODUCT_CLASS_NAME)
self.assertEqual(entitlement.attr.certificate_type, certificate_type) self.assertEqual(entitlement.attr.certificate_type, certificate_type)
self.assertEqual(entitlement.attr.UUID, 'foo-bar') self.assertEqual(entitlement.attr.UUID, self.course_uuid)
self.assertEqual(entitlement.stockrecords.get(partner=self.partner).price_excl_tax, expected['price']) self.assertEqual(entitlement.stockrecords.get(partner=self.partner).price_excl_tax, expected['price'])
def assert_seat_saved(self, course, expected): def assert_seat_saved(self, course, expected):
...@@ -364,6 +346,22 @@ class AtomicPublicationTests(DiscoveryTestMixin, TestCase): ...@@ -364,6 +346,22 @@ class AtomicPublicationTests(DiscoveryTestMixin, TestCase):
self.assertEqual(response.status_code, 400) self.assertEqual(response.status_code, 400)
self.assert_course_does_not_exist(self.course_id) self.assert_course_does_not_exist(self.course_id)
def test_missing_course_uuid(self):
"""Verify that attempting to save a course without a UUID yields a 400."""
self.data.pop('uuid')
response = self.client.post(self.create_path, json.dumps(self.data), JSON_CONTENT_TYPE)
self.assertEqual(response.status_code, 400)
self.assert_course_does_not_exist(self.course_id)
def test_invalid_course_uuid(self):
"""Verify that attempting to save a course with a bad UUID yields a 400."""
self.data['uuid'] = 'foo-bar'
response = self.client.post(self.create_path, json.dumps(self.data), JSON_CONTENT_TYPE)
self.assertEqual(response.status_code, 400)
self.assert_course_does_not_exist(self.course_id)
def test_invalid_product_class(self): def test_invalid_product_class(self):
"""Verify that attempting to save a product with a product class other than 'Seat' yields a 400.""" """Verify that attempting to save a product with a product class other than 'Seat' yields a 400."""
product_class = 'Not a Seat' product_class = 'Not a Seat'
......
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