Skip to content
This repository has been archived by the owner on Nov 4, 2024. It is now read-only.

Commit

Permalink
feat: add variant_id to seat info for ExecEd courses (#4084)
Browse files Browse the repository at this point in the history
  • Loading branch information
AfaqShuaib09 authored Jan 10, 2024
1 parent 1a8335a commit b2dbca2
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 6 deletions.
8 changes: 7 additions & 1 deletion ecommerce/core/tests/test_create_demo_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,13 @@ def test_handle_with_existing_course(self):
partner=self.partner
)

seat_attrs = {'certificate_type': '', 'expires': None, 'price': 0.00, 'id_verification_required': False}
seat_attrs = {
'certificate_type': '',
'expires': None,
'price': 0.00,
'id_verification_required': False,
'variant_id': '00000000-0000-0000-0000-000000000000'
}
course.create_or_update_seat(**seat_attrs)

with mock.patch.object(Course, 'publish_to_lms', return_value=None) as mock_publish:
Expand Down
6 changes: 5 additions & 1 deletion ecommerce/courses/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ def create_or_update_seat(
remove_stale_modes=True,
create_enrollment_code=False,
sku=None,
variant_id=None,
):
"""
Creates and updates course seat products.
Expand All @@ -174,7 +175,8 @@ def create_or_update_seat(
create_enrollment_code(bool): Whether an enrollment code is created in addition to the seat.
sku(str): The partner_sku for the product stored as part of the Stock Record. This is used
to perform a GET on the seat as a unique identifier both Ecommerce and Discovery know about.
variant_id(uuid): The variant_id for the product stored as part of the Stock Record.
It is used specifically in case of Executive Education courses to create enrollment on getsmarter.
Returns:
Product: The seat that has been created or updated.
"""
Expand Down Expand Up @@ -218,6 +220,8 @@ def create_or_update_seat(
seat.attr.certificate_type = certificate_type
seat.attr.course_key = course_id
seat.attr.id_verification_required = id_verification_required
if variant_id:
seat.attr.variant_id = variant_id
if certificate_type in ENROLLMENT_CODE_SEAT_TYPES and create_enrollment_code:
self._create_or_update_enrollment_code(
certificate_type, id_verification_required, self.partner, price, expires
Expand Down
16 changes: 12 additions & 4 deletions ecommerce/courses/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def test_save_creates_parent_seat(self):
self.assertEqual(parent.attr.course_key, course.id)

def assert_course_seat_valid(self, seat, course, certificate_type, id_verification_required, price,
credit_provider=None, credit_hours=None):
credit_provider=None, credit_hours=None, variant_id=None):
""" Ensure the given seat has the correct attribute values. """
self.assertEqual(seat.structure, Product.CHILD)
# pylint: disable=protected-access
Expand All @@ -108,6 +108,9 @@ def assert_course_seat_valid(self, seat, course, certificate_type, id_verificati
self.assertEqual(seat.attr.id_verification_required, id_verification_required)
self.assertEqual(seat.stockrecords.first().price_excl_tax, price)

if variant_id:
self.assertEqual(seat.attr.variant_id, variant_id)

if credit_provider:
self.assertEqual(seat.attr.credit_provider, credit_provider)

Expand All @@ -132,7 +135,8 @@ def test_create_or_update_seat(self):
# Test seat update
price = 10
course.create_or_update_seat(
certificate_type, id_verification_required, price, sku=seat.stockrecords.first().partner_sku
certificate_type, id_verification_required, price, sku=seat.stockrecords.first().partner_sku,
variant_id='00000000-0000-0000-0000-000000000000'
)

# Again, only two seats with one being the parent seat product.
Expand Down Expand Up @@ -202,12 +206,14 @@ def test_update_credit_seat(self):
certificate_type = 'credit'
id_verification_required = True
price = 10
variant_id = '00000000-0000-0000-0000-000000000000'
credit_seat = course.create_or_update_seat(
certificate_type,
id_verification_required,
price,
credit_provider=credit_provider,
credit_hours=credit_hours
credit_hours=credit_hours,
variant_id=variant_id
)
credit_hours = 4
price = 100
Expand All @@ -218,6 +224,7 @@ def test_update_credit_seat(self):
credit_provider=credit_provider,
credit_hours=credit_hours,
sku=credit_seat.stockrecords.first().partner_sku,
variant_id=variant_id
)
self.assert_course_seat_valid(
credit_seat,
Expand All @@ -226,7 +233,8 @@ def test_update_credit_seat(self):
id_verification_required,
price,
credit_provider=credit_provider,
credit_hours=credit_hours
credit_hours=credit_hours,
variant_id=variant_id
)

def test_collision_avoidance(self):
Expand Down
2 changes: 2 additions & 0 deletions ecommerce/extensions/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -771,6 +771,7 @@ def save(course, product, create_enrollment_code):
stockrecords = product.get('stockrecords', [])
if stockrecords:
sku = stockrecords[0].get('partner_sku')
variant_id = attrs.get('variant_id')

seat = course.create_or_update_seat(
certificate_type,
Expand All @@ -781,6 +782,7 @@ def save(course, product, create_enrollment_code):
credit_hours=credit_hours,
create_enrollment_code=create_enrollment_code,
sku=sku,
variant_id=variant_id
)

# As a convenience to our caller, provide the SKU in the returned product serialization.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Generated by Django 3.2.20 on 2024-01-04 09:32

from django.db import migrations

from ecommerce.core.constants import SEAT_PRODUCT_CLASS_NAME


def create_product_attribute(apps, schema_editor):
""" Create a product attribute for course seat product class"""
ProductAttribute = apps.get_model("catalogue", "ProductAttribute")
ProductClass = apps.get_model("catalogue", "ProductClass")

for class_iter in (ProductAttribute, ProductClass):
class_iter.skip_history_when_saving = True

seat = ProductClass.objects.get(name=SEAT_PRODUCT_CLASS_NAME)

# Create product attribute for course seat products
product_attr = ProductAttribute(
product_class=seat,
name="variant_id",
code="variant_id",
type="text",
required=False
)
product_attr.save()

def remove_product_attribute(apps, schema_editor):
""" Reverse function. """
ProductAttribute = apps.get_model("catalogue", "ProductAttribute")
ProductAttribute.skip_history_when_saving = True
ProductAttribute.objects.filter(name='variant_id', product_class__name=SEAT_PRODUCT_CLASS_NAME).delete()

class Migration(migrations.Migration):

dependencies = [
('catalogue', '0055_sf_opp_line_item_ent_attr'),
]

operations = [
migrations.RunPython(create_product_attribute, remove_product_attribute),
]

0 comments on commit b2dbca2

Please sign in to comment.