From 6d1c23b7dccb757bd0859c1c7597ffdd834d7002 Mon Sep 17 00:00:00 2001 From: Renzo Lucioni Date: Fri, 12 May 2017 14:06:37 -0400 Subject: [PATCH] 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 --- .../djangoapps/programs/tests/test_utils.py | 23 ++++++++++--------- openedx/core/djangoapps/programs/utils.py | 16 ++++++------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/openedx/core/djangoapps/programs/tests/test_utils.py b/openedx/core/djangoapps/programs/tests/test_utils.py index 592fb54254..f40513fbc0 100644 --- a/openedx/core/djangoapps/programs/tests/test_utils.py +++ b/openedx/core/djangoapps/programs/tests/test_utils.py @@ -205,32 +205,32 @@ class TestProgramProgressMeter(TestCase): self.assertEqual(meter.progress(count_only=False), expected) - @ddt.data(1, -1) - def test_in_progress_course_upgrade_deadline_check(self, modifier, mock_get_programs): + @ddt.data(None, 1, -1) + 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, 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() now = datetime.datetime.now(utc) - date_modifier = modifier * datetime.timedelta(days=1) - seat_with_upgrade_deadline = SeatFactory(type='test', upgrade_deadline=str(now + date_modifier)) - enrolled_seat = SeatFactory(type='verified') - seats = [seat_with_upgrade_deadline, enrolled_seat] + upgrade_deadline = None if not offset else str(now + datetime.timedelta(days=offset)) + required_seat = SeatFactory(type='verified', upgrade_deadline=upgrade_deadline) + enrolled_seat = SeatFactory(type='audit') + seats = [required_seat, enrolled_seat] data = [ ProgramFactory( courses=[ 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 - self._create_enrollments(course_run_key) + CourseEnrollmentFactory(user=self.user, course_id=course_run_key, mode='audit') meter = ProgramProgressMeter(self.user) @@ -239,10 +239,11 @@ class TestProgramProgressMeter(TestCase): ProgressFactory( uuid=program['uuid'], completed=0, - in_progress=1 if modifier == 1 else 0, - not_started=1 if modifier == -1 else 0 + in_progress=1 if offset in [None, 1] else 0, + not_started=1 if offset in [-1] else 0 ) ] + self.assertEqual(meter.progress(count_only=True), expected) def test_mutiple_program_engagement(self, mock_get_programs): diff --git a/openedx/core/djangoapps/programs/utils.py b/openedx/core/djangoapps/programs/utils.py index 01a151b032..db88090ffe 100644 --- a/openedx/core/djangoapps/programs/utils.py +++ b/openedx/core/djangoapps/programs/utils.py @@ -150,30 +150,28 @@ class ProgramProgressMeter(object): Returns: 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] - # 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 = [ run for run in enrolled_runs if run['type'] == self.enrolled_run_modes[run['key']] ] + 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] if not_failed_runs: 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 = [] for run in enrolled_runs: for seat in run['seats']: if seat['type'] == run['type'] and run['type'] != self.enrolled_run_modes[run['key']]: upgrade_deadlines.append(seat['upgrade_deadline']) - course_still_upgradeable = any( - (deadline is not None) and (parse(deadline) > now) for deadline in upgrade_deadlines - ) - return course_still_upgradeable + # An upgrade deadline of None means the course is always upgradeable. + return any(not deadline or deadline and parse(deadline) > now for deadline in upgrade_deadlines) def progress(self, programs=None, count_only=True): """Gauge a user's progress towards program completion.