')
diff --git a/openedx/features/course_experience/tests/views/test_course_outline.py b/openedx/features/course_experience/tests/views/test_course_outline.py
index 88d413a250..07353f8634 100644
--- a/openedx/features/course_experience/tests/views/test_course_outline.py
+++ b/openedx/features/course_experience/tests/views/test_course_outline.py
@@ -14,6 +14,7 @@ from completion.test_utils import CompletionWaffleTestMixin
from django.contrib.sites.models import Site
from django.test import override_settings
from django.urls import reverse
+from django.utils import timezone
from milestones.tests.utils import MilestonesTestCaseMixin
from mock import Mock, patch
from opaque_keys.edx.keys import CourseKey, UsageKey
@@ -25,6 +26,8 @@ from waffle.testutils import override_switch
from lms.djangoapps.courseware.tests.factories import StaffFactory
from gating import api as lms_gating_api
from lms.djangoapps.course_api.blocks.transformers.milestones import MilestonesAndSpecialExamsTransformer
+from openedx.core.djangoapps.schedules.models import Schedule
+from openedx.core.djangoapps.schedules.tests.factories import ScheduleFactory
from openedx.core.lib.gating import api as gating_api
from openedx.features.course_experience.views.course_outline import (
DEFAULT_COMPLETION_TRACKING_START,
@@ -55,7 +58,7 @@ class TestCourseOutlinePage(SharedModuleStoreTestCase):
# pylint: disable=super-method-not-called
with super(TestCourseOutlinePage, cls).setUpClassAndTestData():
cls.courses = []
- course = CourseFactory.create()
+ course = CourseFactory.create(self_paced=True)
with cls.store.bulk_operations(course.id):
chapter = ItemFactory.create(category='chapter', parent_location=course.location)
sequential = ItemFactory.create(category='sequential', parent_location=chapter.location)
@@ -132,6 +135,18 @@ class TestCourseOutlinePage(SharedModuleStoreTestCase):
self.assertContains(response, sequential.format)
self.assertTrue(sequential.children)
+ def test_reset_course_deadlines(self):
+ course = self.courses[0]
+ enrollment = CourseEnrollment.objects.get(course_id=course.id)
+ ScheduleFactory(
+ start_date=timezone.now() - datetime.timedelta(1),
+ enrollment=enrollment
+ )
+ url = '{}{}'.format(course_home_url(course), 'reset_deadlines')
+ self.client.post(url)
+ updated_schedule = Schedule.objects.get(enrollment=enrollment)
+ self.assertEqual(updated_schedule.start_date.day, datetime.datetime.today().day)
+
class TestCourseOutlinePageWithPrerequisites(SharedModuleStoreTestCase, MilestonesTestCaseMixin):
"""
diff --git a/openedx/features/course_experience/urls.py b/openedx/features/course_experience/urls.py
index 14a96b7ac5..1a444ab99a 100644
--- a/openedx/features/course_experience/urls.py
+++ b/openedx/features/course_experience/urls.py
@@ -7,7 +7,7 @@ from django.conf.urls import url
from .views.course_dates import CourseDatesFragmentMobileView
from .views.course_home import CourseHomeFragmentView, CourseHomeView
-from .views.course_outline import CourseOutlineFragmentView
+from .views.course_outline import CourseOutlineFragmentView, reset_course_deadlines
from .views.course_reviews import CourseReviewsView
from .views.course_sock import CourseSockFragmentView
from .views.course_updates import CourseUpdatesFragmentView, CourseUpdatesView
@@ -70,4 +70,9 @@ urlpatterns = [
CourseDatesFragmentMobileView.as_view(),
name='openedx.course_experience.mobile_dates_fragment_view',
),
+ url(
+ r'^reset_deadlines$',
+ reset_course_deadlines,
+ name='openedx.course_experience.reset_course_deadlines',
+ ),
]
diff --git a/openedx/features/course_experience/views/course_outline.py b/openedx/features/course_experience/views/course_outline.py
index bab2cdc485..228aa2c480 100644
--- a/openedx/features/course_experience/views/course_outline.py
+++ b/openedx/features/course_experience/views/course_outline.py
@@ -5,11 +5,16 @@ Views to show a course outline.
import datetime
import re
+import pytz
+import six
from completion import waffle as completion_waffle
from django.contrib.auth.models import User
+from django.shortcuts import redirect
from django.template.context_processors import csrf
from django.template.loader import render_to_string
+from django.urls import reverse
+from django.views.decorators.csrf import ensure_csrf_cookie
import edx_when.api as edx_when_api
from opaque_keys.edx.keys import CourseKey
from pytz import UTC
@@ -17,6 +22,7 @@ from waffle.models import Switch
from web_fragments.fragment import Fragment
from lms.djangoapps.courseware.courses import get_course_overview_with_access
+from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
from openedx.core.djangoapps.plugin_api.views import EdxFragmentView
from student.models import CourseEnrollment
from util.milestones_helpers import get_course_content_milestones
@@ -154,3 +160,19 @@ class CourseOutlineFragmentView(EdxFragmentView):
if children:
children[0]['resume_block'] = True
self.mark_first_unit_to_resume(children[0])
+
+
+@ensure_csrf_cookie
+def reset_course_deadlines(request, course_id):
+ """
+ Set the start_date of a schedule to today, which in turn will adjust due dates for
+ sequentials belonging to a self paced course
+ """
+ course = CourseOverview.objects.get(id=course_id)
+ if course.self_paced:
+ enrollment = CourseEnrollment.objects.get(user=request.user, course=course_id)
+ schedule = enrollment.schedule
+ if schedule:
+ schedule.start_date = datetime.datetime.now(pytz.utc)
+ schedule.save()
+ return redirect(reverse('openedx.course_experience.course_home', args=[six.text_type(course_id)]))