Commit 96eac3b5 by Clinton Blackburn Committed by Clinton Blackburn

Updated date publishing for E-Commerce API calls

- Verification deadline now defaults to the course end date
- Product expiration date (upgrade deadline) now defaults to course a few days before the course end date

LEARNER-2621
parent 7008beb1
import datetime
import random
import pytest
from course_discovery.apps.core.utils import serialize_datetime
from course_discovery.apps.publisher.api.utils import serialize_seat_for_ecommerce_api
from course_discovery.apps.publisher.models import Seat
from course_discovery.apps.publisher.tests.factories import SeatFactory
@pytest.mark.django_db
class TestSerializeSeatForEcommerceApi:
def test_serialize_seat_for_ecommerce_api(self):
seat = SeatFactory()
actual = serialize_seat_for_ecommerce_api(seat)
assert actual['price'] == str(seat.price)
assert actual['product_class'] == 'Seat'
def test_serialize_seat_for_ecommerce_api_with_audit_seat(self):
seat = SeatFactory(type=Seat.AUDIT)
actual = serialize_seat_for_ecommerce_api(seat)
expected = {
'expires': serialize_datetime(seat.upgrade_deadline),
'price': str(seat.price),
'product_class': 'Seat',
'attribute_values': [
{
'name': 'certificate_type',
'value': None,
},
{
'name': 'id_verification_required',
'value': False,
}
]
}
assert actual == expected
def test_serialize_seat_for_ecommerce_api_without_upgrade_deadline(self, settings):
settings.PUBLISHER_UPGRADE_DEADLINE_DAYS = random.randint(1, 21)
now = datetime.datetime.utcnow()
seat = SeatFactory(upgrade_deadline=None, course_run__end=now)
actual = serialize_seat_for_ecommerce_api(seat)
assert actual['expires'] == serialize_datetime(
now - datetime.timedelta(days=settings.PUBLISHER_UPGRADE_DEADLINE_DAYS))
@pytest.mark.parametrize('seat_type', (Seat.VERIFIED, Seat.PROFESSIONAL))
def test_serialize_seat_for_ecommerce_api_with_id_verification(self, seat_type):
seat = SeatFactory(type=seat_type)
actual = serialize_seat_for_ecommerce_api(seat)
expected_attribute_values = [
{
'name': 'certificate_type',
'value': seat_type,
},
{
'name': 'id_verification_required',
'value': True,
}
]
assert actual['attribute_values'] == expected_attribute_values
import datetime
from django.conf import settings
from course_discovery.apps.core.utils import serialize_datetime
from course_discovery.apps.publisher.models import Seat
def serialize_seat_for_ecommerce_api(seat):
upgrade_deadline = seat.upgrade_deadline
if not upgrade_deadline:
upgrade_deadline = seat.course_run.end - datetime.timedelta(days=settings.PUBLISHER_UPGRADE_DEADLINE_DAYS)
return {
'expires': serialize_datetime(upgrade_deadline),
'price': str(seat.price),
'product_class': 'Seat',
'attribute_values': [
{
'name': 'certificate_type',
'value': None if seat.type == Seat.AUDIT else seat.type,
},
{
'name': 'id_verification_required',
'value': seat.type in (Seat.VERIFIED, Seat.PROFESSIONAL),
}
]
}
......@@ -7,11 +7,14 @@ from rest_framework.test import APITestCase
from course_discovery.apps.core.models import Partner
from course_discovery.apps.core.tests.factories import StaffUserFactory, UserFactory
from course_discovery.apps.core.utils import serialize_datetime
from course_discovery.apps.course_metadata.models import CourseRun, Video
from course_discovery.apps.course_metadata.tests.factories import OrganizationFactory, PersonFactory
from course_discovery.apps.ietf_language_tags.models import LanguageTag
from course_discovery.apps.publisher.api.utils import serialize_seat_for_ecommerce_api
from course_discovery.apps.publisher.api.v1.views import CourseRunViewSet
from course_discovery.apps.publisher.tests.factories import CourseRunFactory
from course_discovery.apps.publisher.models import Seat
from course_discovery.apps.publisher.tests.factories import CourseRunFactory, SeatFactory
class CourseRunViewSetTests(APITestCase):
......@@ -64,10 +67,32 @@ class CourseRunViewSetTests(APITestCase):
url = '{root}publication/'.format(root=partner.ecommerce_api_url)
responses.add(responses.POST, url, json=body, status=status)
def serialize_seat_for_ecommerce_api(self, seat):
return {
'expires': serialize_datetime(seat.upgrade_deadline or seat.course_run.end),
'price': str(seat.price),
'product_class': 'Seat',
'attribute_values': [
{
'name': 'certificate_type',
'value': None if seat.type is Seat.AUDIT else seat.type,
},
{
'name': 'id_verification_required',
'value': seat.type in (Seat.VERIFIED, Seat.PROFESSIONAL),
}
]
}
@responses.activate
@mock.patch.object(Partner, 'access_token', return_value='JWT fake')
def test_publish(self, mock_access_token): # pylint: disable=unused-argument
def test_publish(self, mock_access_token): # pylint: disable=unused-argument,too-many-statements
publisher_course_run = self._create_course_run_for_publication()
audit_seat = SeatFactory(course_run=publisher_course_run, type=Seat.AUDIT, upgrade_deadline=None)
professional_seat = SeatFactory(course_run=publisher_course_run, type=Seat.PROFESSIONAL)
verified_seat = SeatFactory(course_run=publisher_course_run, type=Seat.VERIFIED)
partner = publisher_course_run.course.organizations.first().partner
self._set_test_client_domain_and_login(partner)
......@@ -85,6 +110,16 @@ class CourseRunViewSetTests(APITestCase):
}
assert response.data == expected
# Verify the correct deadlines were sent to the E-Commerce API
ecommerce_body = json.loads(responses.calls[2].request.body)
expected = [
serialize_seat_for_ecommerce_api(audit_seat),
serialize_seat_for_ecommerce_api(professional_seat),
serialize_seat_for_ecommerce_api(verified_seat),
]
assert ecommerce_body['products'] == expected
assert ecommerce_body['verification_deadline'] == serialize_datetime(publisher_course_run.end)
discovery_course_run = CourseRun.objects.get(key=publisher_course_run.lms_course_id)
publisher_course = publisher_course_run.course
discovery_course = discovery_course_run.course
......
......@@ -11,7 +11,8 @@ from slumber.exceptions import SlumberBaseException
from course_discovery.apps.core.utils import serialize_datetime
from course_discovery.apps.course_metadata.models import CourseRun as DiscoveryCourseRun
from course_discovery.apps.course_metadata.models import Course, Video
from course_discovery.apps.publisher.models import CourseRun, Seat
from course_discovery.apps.publisher.api.utils import serialize_seat_for_ecommerce_api
from course_discovery.apps.publisher.models import CourseRun
from course_discovery.apps.publisher.studio_api_utils import StudioAPI
logger = logging.getLogger(__name__)
......@@ -72,25 +73,10 @@ class CourseRunViewSet(viewsets.GenericViewSet):
data = {
'id': course_run.lms_course_id,
'name': course_run.title_override or course_run.course.title,
'verification_deadline': None,
'verification_deadline': serialize_datetime(course_run.end),
'create_or_activate_enrollment_code': False,
'products': [
{
'expires': serialize_datetime(seat.upgrade_deadline),
'price': str(seat.price),
'product_class': 'Seat',
'attribute_values': [
{
'name': 'certificate_type',
'value': None if seat.type is Seat.AUDIT else seat.type,
},
{
'name': 'id_verification_required',
'value': seat.type in (Seat.VERIFIED, Seat.PROFESSIONAL),
}
]
} for seat in course_run.seats.all()
]
# NOTE (CCB): We only order here to aid testing. The E-Commerce API does NOT care about ordering.
'products': [serialize_seat_for_ecommerce_api(seat) for seat in course_run.seats.all().order_by('created')],
}
try:
......
......@@ -501,6 +501,10 @@ SOLO_CACHE_TIMEOUT = 3600
PUBLISHER_FROM_EMAIL = None
# If no upgrade deadline is specified for a course run seat, when the course is published the deadline will default to
# the course run end date minus the specified number of days.
PUBLISHER_UPGRADE_DEADLINE_DAYS = 10
# Django Debug Toolbar settings
# http://django-debug-toolbar.readthedocs.org/en/latest/installation.html
if os.environ.get('ENABLE_DJANGO_TOOLBAR', False):
......
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