Commit 6d1c23b7 by Renzo Lucioni

Treat empty upgrade deadlines consistently

The course and program dashboards interpret an empty upgrade deadline to mean that a given seat is available. Previously, program dashboard pages interpreted empty upgrade deadlines to mean that a given seat was not available.

LEARNER-935
parent 8312abdb
...@@ -205,32 +205,32 @@ class TestProgramProgressMeter(TestCase): ...@@ -205,32 +205,32 @@ class TestProgramProgressMeter(TestCase):
self.assertEqual(meter.progress(count_only=False), expected) self.assertEqual(meter.progress(count_only=False), expected)
@ddt.data(1, -1) @ddt.data(None, 1, -1)
def test_in_progress_course_upgrade_deadline_check(self, modifier, mock_get_programs): def test_in_progress_course_upgrade_deadline_check(self, offset, mock_get_programs):
""" """
Verify that if the user's enrollment is not of the same type as the course run, Verify that if the user's enrollment is not of the same type as the course run,
the course will only count as in progress if there is another available seat with the course will only count as in progress if there is another available seat with
the right type, where the upgrade deadline has not expired. the right type for which the upgrade deadline has not passed.
""" """
course_run_key = generate_course_run_key() course_run_key = generate_course_run_key()
now = datetime.datetime.now(utc) now = datetime.datetime.now(utc)
date_modifier = modifier * datetime.timedelta(days=1) upgrade_deadline = None if not offset else str(now + datetime.timedelta(days=offset))
seat_with_upgrade_deadline = SeatFactory(type='test', upgrade_deadline=str(now + date_modifier)) required_seat = SeatFactory(type='verified', upgrade_deadline=upgrade_deadline)
enrolled_seat = SeatFactory(type='verified') enrolled_seat = SeatFactory(type='audit')
seats = [seat_with_upgrade_deadline, enrolled_seat] seats = [required_seat, enrolled_seat]
data = [ data = [
ProgramFactory( ProgramFactory(
courses=[ courses=[
CourseFactory(course_runs=[ CourseFactory(course_runs=[
CourseRunFactory(key=course_run_key, type='test', seats=seats), CourseRunFactory(key=course_run_key, type='verified', seats=seats),
]), ]),
] ]
) )
] ]
mock_get_programs.return_value = data mock_get_programs.return_value = data
self._create_enrollments(course_run_key) CourseEnrollmentFactory(user=self.user, course_id=course_run_key, mode='audit')
meter = ProgramProgressMeter(self.user) meter = ProgramProgressMeter(self.user)
...@@ -239,10 +239,11 @@ class TestProgramProgressMeter(TestCase): ...@@ -239,10 +239,11 @@ class TestProgramProgressMeter(TestCase):
ProgressFactory( ProgressFactory(
uuid=program['uuid'], uuid=program['uuid'],
completed=0, completed=0,
in_progress=1 if modifier == 1 else 0, in_progress=1 if offset in [None, 1] else 0,
not_started=1 if modifier == -1 else 0 not_started=1 if offset in [-1] else 0
) )
] ]
self.assertEqual(meter.progress(count_only=True), expected) self.assertEqual(meter.progress(count_only=True), expected)
def test_mutiple_program_engagement(self, mock_get_programs): def test_mutiple_program_engagement(self, mock_get_programs):
......
...@@ -150,30 +150,28 @@ class ProgramProgressMeter(object): ...@@ -150,30 +150,28 @@ class ProgramProgressMeter(object):
Returns: Returns:
bool, indicating whether the course is in progress. bool, indicating whether the course is in progress.
""" """
# Part 1: Check if any of the seats you are enrolled in qualify this course as in progress
enrolled_runs = [run for run in course['course_runs'] if run['key'] in self.course_run_ids] enrolled_runs = [run for run in course['course_runs'] if run['key'] in self.course_run_ids]
# Check if the user is enrolled in the required mode for the run
# Check if the user is enrolled in a required run and mode/seat.
runs_with_required_mode = [ runs_with_required_mode = [
run for run in enrolled_runs run for run in enrolled_runs
if run['type'] == self.enrolled_run_modes[run['key']] if run['type'] == self.enrolled_run_modes[run['key']]
] ]
if runs_with_required_mode: if runs_with_required_mode:
# Check if the runs you are enrolled in with the right mode are not failed
not_failed_runs = [run for run in runs_with_required_mode if run not in self.failed_course_runs] not_failed_runs = [run for run in runs_with_required_mode if run not in self.failed_course_runs]
if not_failed_runs: if not_failed_runs:
return True return True
# Part 2: Check if any of the seats you are not enrolled in
# in the runs you are enrolled in qualify this course as in progress # Check if seats required for course completion are still available.
upgrade_deadlines = [] upgrade_deadlines = []
for run in enrolled_runs: for run in enrolled_runs:
for seat in run['seats']: for seat in run['seats']:
if seat['type'] == run['type'] and run['type'] != self.enrolled_run_modes[run['key']]: if seat['type'] == run['type'] and run['type'] != self.enrolled_run_modes[run['key']]:
upgrade_deadlines.append(seat['upgrade_deadline']) upgrade_deadlines.append(seat['upgrade_deadline'])
course_still_upgradeable = any( # An upgrade deadline of None means the course is always upgradeable.
(deadline is not None) and (parse(deadline) > now) for deadline in upgrade_deadlines return any(not deadline or deadline and parse(deadline) > now for deadline in upgrade_deadlines)
)
return course_still_upgradeable
def progress(self, programs=None, count_only=True): def progress(self, programs=None, count_only=True):
"""Gauge a user's progress towards program completion. """Gauge a user's progress towards program completion.
......
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