Merge pull request #16174 from edx/aj/LEARNER-2715
Bug fix for unpublished courses that users have purchased within a pr…
This commit is contained in:
@@ -550,7 +550,7 @@ class TestProgramProgressMeter(TestCase):
|
||||
self.assertEqual(meter._is_course_complete(course), True)
|
||||
|
||||
|
||||
def _create_course(self, course_price):
|
||||
def _create_course(self, course_price, course_run_count=1):
|
||||
"""
|
||||
Creates the course in mongo and update it with the instructor data.
|
||||
Also creates catalog course with respect to course run.
|
||||
@@ -558,17 +558,18 @@ def _create_course(self, course_price):
|
||||
Returns:
|
||||
Catalog course dict.
|
||||
"""
|
||||
course = ModuleStoreCourseFactory()
|
||||
course.start = datetime.datetime.now(utc) - datetime.timedelta(days=1)
|
||||
course.end = datetime.datetime.now(utc) + datetime.timedelta(days=1)
|
||||
course.instructor_info = self.instructors
|
||||
course = self.update_course(course, self.user.id)
|
||||
course_runs = []
|
||||
for x in range(course_run_count):
|
||||
course = ModuleStoreCourseFactory.create(run='Run_' + str(x))
|
||||
course.start = datetime.datetime.now(utc) - datetime.timedelta(days=1)
|
||||
course.end = datetime.datetime.now(utc) + datetime.timedelta(days=1)
|
||||
course.instructor_info = self.instructors
|
||||
course = self.update_course(course, self.user.id)
|
||||
|
||||
course_run = CourseRunFactory(
|
||||
key=unicode(course.id),
|
||||
seats=[SeatFactory(price=course_price)]
|
||||
)
|
||||
return CourseFactory(course_runs=[course_run])
|
||||
run = CourseRunFactory(key=unicode(course.id), seats=[SeatFactory(price=course_price)])
|
||||
course_runs.append(run)
|
||||
|
||||
return CourseFactory(course_runs=course_runs)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@@ -810,6 +811,25 @@ class TestProgramDataExtender(ModuleStoreTestCase):
|
||||
data = ProgramDataExtender(program2, self.user).extend()
|
||||
self.assertTrue(data['is_learner_eligible_for_one_click_purchase'])
|
||||
|
||||
def test_learner_eligibility_for_one_click_purchase_with_unpublished(self):
|
||||
"""
|
||||
Learner should be eligible for one click purchase if:
|
||||
- program is eligible for one click purchase
|
||||
- There are courses remaining that have not been purchased and enrolled in.
|
||||
"""
|
||||
course1 = _create_course(self, self.course_price, course_run_count=2)
|
||||
course2 = _create_course(self, self.course_price)
|
||||
CourseEnrollmentFactory(user=self.user, course_id=course1['course_runs'][0]['key'], mode='verified')
|
||||
course1['course_runs'][0]['status'] = 'unpublished'
|
||||
program2 = ProgramFactory(
|
||||
courses=[course1, course2],
|
||||
is_program_eligible_for_one_click_purchase=True,
|
||||
applicable_seat_types=['verified'],
|
||||
)
|
||||
data = ProgramDataExtender(program2, self.user).extend()
|
||||
self.assertEqual(len(data['skus']), 1)
|
||||
self.assertTrue(data['is_learner_eligible_for_one_click_purchase'])
|
||||
|
||||
def test_learner_eligibility_for_one_click_purchase_professional_no_id(self):
|
||||
"""
|
||||
Learner should not be eligible for one click purchase if:
|
||||
|
||||
@@ -451,6 +451,22 @@ class ProgramDataExtender(object):
|
||||
def _attach_course_run_may_certify(self, run_mode):
|
||||
run_mode['may_certify'] = self.course_overview.may_certify()
|
||||
|
||||
def _check_enrollment_for_user(self, course_run):
|
||||
applicable_seat_types = self.data['applicable_seat_types']
|
||||
|
||||
(enrollment_mode, active) = CourseEnrollment.enrollment_mode_for_user(
|
||||
self.user,
|
||||
CourseKey.from_string(course_run['key'])
|
||||
)
|
||||
|
||||
is_paid_seat = False
|
||||
if enrollment_mode is not None and active is not None and active is True:
|
||||
# Check all the applicable seat types
|
||||
# this will also check for no-id-professional as professional
|
||||
is_paid_seat = any(seat_type in enrollment_mode for seat_type in applicable_seat_types)
|
||||
|
||||
return is_paid_seat
|
||||
|
||||
def _collect_one_click_purchase_eligibility_data(self):
|
||||
"""
|
||||
Extend the program data with data about learner's eligibility for one click purchase,
|
||||
@@ -462,27 +478,17 @@ class ProgramDataExtender(object):
|
||||
bundle_variant = 'full'
|
||||
if is_learner_eligible_for_one_click_purchase:
|
||||
for course in self.data['courses']:
|
||||
add_course_sku = False
|
||||
published_course_runs = filter(lambda run: run['status'] == 'published', course['course_runs'])
|
||||
add_course_sku = True
|
||||
course_runs = course.get('course_runs', [])
|
||||
published_course_runs = filter(lambda run: run['status'] == 'published', course_runs)
|
||||
|
||||
if len(published_course_runs) == 1:
|
||||
# Look at the course runs for a course and determine if the course SKU should be added.
|
||||
course_run = published_course_runs[0]
|
||||
(enrollment_mode, active) = CourseEnrollment.enrollment_mode_for_user(
|
||||
self.user,
|
||||
CourseKey.from_string(course_run['key'])
|
||||
)
|
||||
for course_run in course_runs:
|
||||
is_paid_seat = self._check_enrollment_for_user(course_run)
|
||||
|
||||
if enrollment_mode is not None and active is not None:
|
||||
# Check all the applicable seat types
|
||||
# this will also check for no-id-professional as professional
|
||||
applicable_seat = any(seat_type in enrollment_mode for seat_type in applicable_seat_types)
|
||||
|
||||
# If no applicable seat is found add the course SKU to the list
|
||||
if not applicable_seat or not active:
|
||||
add_course_sku = True
|
||||
else:
|
||||
# There is no enrollment information for the course add the course SKU
|
||||
add_course_sku = True
|
||||
if is_paid_seat:
|
||||
add_course_sku = False
|
||||
break
|
||||
|
||||
if add_course_sku:
|
||||
for seat in published_course_runs[0]['seats']:
|
||||
|
||||
Reference in New Issue
Block a user