Commit e7c67e1a by Matthew Piatetsky

Add marketable_enrollable_course_runs_with_archived param to programs

ECOM-7262
parent 53572754
...@@ -642,10 +642,18 @@ class MinimalProgramSerializer(serializers.ModelSerializer): ...@@ -642,10 +642,18 @@ class MinimalProgramSerializer(serializers.ModelSerializer):
read_only_fields = ('uuid', 'marketing_url', 'banner_image') read_only_fields = ('uuid', 'marketing_url', 'banner_image')
def get_courses(self, program): def get_courses(self, program):
course_runs = list(program.course_runs)
if self.context.get('marketable_enrollable_course_runs_with_archived'):
marketable_enrollable_course_runs = set()
for course in program.courses.all():
marketable_enrollable_course_runs.update(course.course_runs.marketable().enrollable())
course_runs = list(set(course_runs).intersection(marketable_enrollable_course_runs))
if program.order_courses_by_start_date: if program.order_courses_by_start_date:
courses, course_runs = self.sort_courses(program) courses = self.sort_courses(program, course_runs)
else: else:
courses, course_runs = program.courses.all(), list(program.course_runs) courses = program.courses.all()
course_serializer = MinimalProgramCourseSerializer( course_serializer = MinimalProgramCourseSerializer(
courses, courses,
...@@ -662,7 +670,7 @@ class MinimalProgramSerializer(serializers.ModelSerializer): ...@@ -662,7 +670,7 @@ class MinimalProgramSerializer(serializers.ModelSerializer):
return course_serializer.data return course_serializer.data
def sort_courses(self, program): def sort_courses(self, program, course_runs):
""" """
Sorting by enrollment start then by course start yields a list ordered by course start, with Sorting by enrollment start then by course start yields a list ordered by course start, with
ties broken by enrollment start. This works because Python sorting is stable: two objects with ties broken by enrollment start. This works because Python sorting is stable: two objects with
...@@ -672,7 +680,6 @@ class MinimalProgramSerializer(serializers.ModelSerializer): ...@@ -672,7 +680,6 @@ class MinimalProgramSerializer(serializers.ModelSerializer):
course_runs should never be empty. If it is, key functions in this method attempting to find the course_runs should never be empty. If it is, key functions in this method attempting to find the
min of an empty sequence will raise a ValueError. min of an empty sequence will raise a ValueError.
""" """
course_runs = list(program.course_runs)
def min_run_enrollment_start(course): def min_run_enrollment_start(course):
# Enrollment starts may be empty. When this is the case, we make the same assumption as # Enrollment starts may be empty. When this is the case, we make the same assumption as
...@@ -715,7 +722,7 @@ class MinimalProgramSerializer(serializers.ModelSerializer): ...@@ -715,7 +722,7 @@ class MinimalProgramSerializer(serializers.ModelSerializer):
courses.sort(key=min_run_enrollment_start) courses.sort(key=min_run_enrollment_start)
courses.sort(key=min_run_start) courses.sort(key=min_run_start)
return courses, course_runs return courses
class ProgramSerializer(MinimalProgramSerializer): class ProgramSerializer(MinimalProgramSerializer):
......
...@@ -892,6 +892,45 @@ class ProgramSerializerTests(MinimalProgramSerializerTests): ...@@ -892,6 +892,45 @@ class ProgramSerializerTests(MinimalProgramSerializerTests):
course_run_with_seats = program_with_seats['courses'][0]['course_runs'][0] course_run_with_seats = program_with_seats['courses'][0]['course_runs'][0]
assert 'seats' in course_run_with_seats assert 'seats' in course_run_with_seats
def test_marketable_enrollable_course_runs_with_archived(self):
""" Test that the marketable_enrollable_course_runs_with_archived flag hides course runs
that are not marketable or enrollable
"""
course = CourseFactory()
CourseRunFactory(status=CourseRunStatus.Unpublished, course=course)
marketable_enrollable_run = CourseRunFactory(
status=CourseRunStatus.Published,
end=datetime.datetime.now(pytz.UTC) + datetime.timedelta(days=10),
enrollment_start=None,
enrollment_end=None,
course=course
)
SeatFactory(course_run=marketable_enrollable_run)
program = ProgramFactory(courses=[course])
request = make_request()
serializer = self.serializer_class(
program,
context={
'request': request,
'marketable_enrollable_course_runs_with_archived': True
}
)
expected = MinimalProgramCourseSerializer(
[course],
many=True,
context={
'request': request,
'program': program,
'course_runs': [marketable_enrollable_run]
}
).data
assert len(expected[0]['course_runs']) == 1
assert sorted(serializer.data['courses'][0]['course_runs'], key=lambda x: x['key']) == \
sorted(expected[0]['course_runs'], key=lambda x: x['key'])
class ProgramTypeSerializerTests(TestCase): class ProgramTypeSerializerTests(TestCase):
serializer_class = ProgramTypeSerializer serializer_class = ProgramTypeSerializer
......
...@@ -34,11 +34,10 @@ class ProgramViewSet(viewsets.ReadOnlyModelViewSet): ...@@ -34,11 +34,10 @@ class ProgramViewSet(viewsets.ReadOnlyModelViewSet):
def get_serializer_context(self, *args, **kwargs): def get_serializer_context(self, *args, **kwargs):
context = super().get_serializer_context(*args, **kwargs) context = super().get_serializer_context(*args, **kwargs)
context.update({ query_params = ['exclude_utm', 'use_full_course_serializer', 'published_course_runs_only',
'published_course_runs_only': get_query_param(self.request, 'published_course_runs_only'), 'marketable_enrollable_course_runs_with_archived']
'exclude_utm': get_query_param(self.request, 'exclude_utm'), for query_param in query_params:
'use_full_course_serializer': get_query_param(self.request, 'use_full_course_serializer'), context[query_param] = get_query_param(self.request, query_param)
})
return context return context
...@@ -65,6 +64,13 @@ class ProgramViewSet(viewsets.ReadOnlyModelViewSet): ...@@ -65,6 +64,13 @@ class ProgramViewSet(viewsets.ReadOnlyModelViewSet):
type: integer type: integer
paramType: query paramType: query
mulitple: false mulitple: false
- name: marketable_enrollable_course_runs_with_archived
description: Restrict returned course runs to those that are published, have seats,
and can be enrolled in now. Includes archived courses.
required: false
type: integer
paramType: query
mulitple: false
- name: exclude_utm - name: exclude_utm
description: Exclude UTM parameters from marketing URLs. description: Exclude UTM parameters from marketing URLs.
required: false required: 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