def reset_course_deadlines(request): course_key = request.data.get('course_key', None) # If body doesnt contain 'course_key', return 400 to client. if not course_key: raise ParseError(_("'course_key' is required.")) # If body contains params other than 'course_key', return 400 to client. if len(request.data) > 1: raise ParseError(_("Only 'course_key' is expected.")) try: reset_self_paced_schedule(request.user, course_key) key = CourseKey.from_string(course_key) if course_home_mfe_dates_tab_is_active(key): body_link = get_microfrontend_url(course_key=course_key, view_name='dates') else: body_link = '{}{}'.format(settings.LMS_ROOT_URL, reverse('dates', args=[six.text_type(course_key)])) return Response({ 'body': format_html('<a href="{}">{}</a>', body_link, _('View all dates')), 'header': format_html( '<div>{}</div>', _('Your due dates have been successfully shifted to help you stay on track.') ), 'message': _('Deadlines successfully reset.'), }) except Exception: raise UnableToResetDeadlines
def reset_course_deadlines(request): """ Set the start_date of a schedule to today, which in turn will adjust due dates for sequentials belonging to a self paced course """ from lms.urls import RENDER_XBLOCK_NAME from openedx.features.course_experience.urls import COURSE_HOME_VIEW_NAME detail_id_dict = ast.literal_eval( request.POST.get('reset_deadlines_redirect_url_id_dict')) redirect_url = request.POST.get('reset_deadlines_redirect_url_base', COURSE_HOME_VIEW_NAME) course_key = CourseKey.from_string(detail_id_dict['course_id']) masquerade_details, masquerade_user = setup_masquerade( request, course_key, has_access(request.user, 'staff', course_key)) if masquerade_details and masquerade_details.role == 'student' and masquerade_details.user_name and ( redirect_url == COURSE_HOME_VIEW_NAME): # Masquerading as a specific student, so reset that student's schedule user = masquerade_user else: user = request.user reset_self_paced_schedule(user, course_key) if redirect_url == RENDER_XBLOCK_NAME: detail_id_dict.pop('course_id') return redirect(reverse(redirect_url, kwargs=detail_id_dict))
def reset_schedule_on_mode_change(sender, user, course_key, mode, **kwargs): # pylint: disable=unused-argument """ When a CourseEnrollment's mode is changed, reset the user's schedule if self-paced. """ # If switching to audit, reset to when the user got access to course. This is for the case where a user # upgrades to verified (resetting their date), then later refunds the order and goes back to audit. We want # to make sure that audit users go back to their normal audit schedule access. use_availability_date = mode in CourseMode.AUDIT_MODES reset_self_paced_schedule(user, course_key, use_availability_date=use_availability_date)
def test_safe_without_schedule(self): """ Just ensure that we don't raise exceptions or create any schedules """ self.create_schedule() self.schedule.delete() reset_self_paced_schedule(self.user, self.course.id, use_availability_date=False) reset_self_paced_schedule(self.user, self.course.id, use_availability_date=True) self.assertEqual(Schedule.objects.count(), 0)
def test_reset_to_start_date(self, offset, expected_offset): self.create_schedule(offset=offset) expected_start = self.course.start + datetime.timedelta(days=expected_offset) with self.assertNumQueries(3): reset_self_paced_schedule(self.user, self.course.id, use_availability_date=True) self.schedule.refresh_from_db() self.assertEqual(self.schedule.start_date.replace(microsecond=0), expected_start.replace(microsecond=0))
def test_reset_to_now(self): self.create_schedule() original_start = self.schedule.start_date with self.assertNumQueries(3): reset_self_paced_schedule(self.user, self.course.id, use_availability_date=False) self.schedule.refresh_from_db() self.assertGreater(self.schedule.start_date, original_start)
def test_reset_before_course_starts(self, use_enrollment_date): self.create_schedule( enrollment_offset=-5, course_start_offset=5) # starts in 5 days, enrollment is now reset_self_paced_schedule(self.user, self.course.id, use_enrollment_date=use_enrollment_date) self.schedule.refresh_from_db() assert self.schedule.start_date == self.enrollment.course.start
def test_reset_to_now(self): self.create_schedule() original_start = self.schedule.start_date with self.assertNumQueries(3): reset_self_paced_schedule(self.user, self.course.id, use_enrollment_date=False) self.schedule.refresh_from_db() assert self.schedule.start_date > original_start
def test_safe_without_schedule(self): """ Just ensure that we don't raise exceptions or create any schedules """ self.create_schedule() self.schedule.delete() reset_self_paced_schedule(self.user, self.course.id, use_enrollment_date=False) reset_self_paced_schedule(self.user, self.course.id, use_enrollment_date=True) assert Schedule.objects.count() == 0
def reset_course_deadlines(request): """ Set the start_date of a schedule to today, which in turn will adjust due dates for sequentials belonging to a self paced course IMPORTANT NOTE: If updates are happening to the logic here, ALSO UPDATE the `reset_course_deadlines` function in common/djangoapps/util/views.py as well. """ course_key = request.data.get('course_key', None) # If body doesnt contain 'course_key', return 400 to client. if not course_key: raise ParseError(_("'course_key' is required.")) # If body contains params other than 'course_key', return 400 to client. if len(request.data) > 1: raise ParseError(_("Only 'course_key' is expected.")) try: course_key = CourseKey.from_string(course_key) _course_masquerade, user = setup_masquerade( request, course_key, has_access(request.user, 'staff', course_key)) missed_deadlines, missed_gated_content = dates_banner_should_display( course_key, user) if missed_deadlines and not missed_gated_content: reset_self_paced_schedule(user, course_key) if course_home_mfe_dates_tab_is_active(course_key): body_link = get_microfrontend_url(course_key=str(course_key), view_name='dates') else: body_link = '{}{}'.format(settings.LMS_ROOT_URL, reverse('dates', args=[str(course_key)])) return Response({ 'body': format_html('<a href="{}">{}</a>', body_link, _('View all dates')), 'header': _('Your due dates have been successfully shifted to help you stay on track.' ), 'link': body_link, 'link_text': _('View all dates'), 'message': _('Deadlines successfully reset.'), }) except Exception as e: log.exception(e) raise UnableToResetDeadlines
def reset_course_deadlines(request): """ 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_key = CourseKey.from_string(request.POST.get('course_id')) _course_masquerade, user = setup_masquerade( request, course_key, has_access(request.user, 'staff', course_key)) missed_deadlines, missed_gated_content = dates_banner_should_display( course_key, user) if missed_deadlines and not missed_gated_content: reset_self_paced_schedule(user, course_key) referrer = request.META.get('HTTP_REFERER') return redirect(referrer) if referrer else HttpResponse()
def reset_course_deadlines(request): course_key = request.data.get('course_key', None) # If body doesnt contain 'course_key', return 400 to client. if not course_key: raise ParseError("'course_key' is required.") # If body contains params other than 'course_key', return 400 to client. if len(request.data) > 1: raise ParseError("Only 'course_key' is expected.") try: reset_self_paced_schedule(request.user, course_key) return Response({'message': 'Deadlines successfully reset.'}) except Exception: raise UnableToResetDeadlines
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_key = CourseKey.from_string(course_id) masquerade_details, masquerade_user = setup_masquerade( request, course_key, has_access(request.user, 'staff', course_key)) if masquerade_details and masquerade_details.role == 'student' and masquerade_details.user_name: # Masquerading as a specific student, so reset that student's schedule user = masquerade_user else: user = request.user reset_self_paced_schedule(user, course_key) return redirect( reverse('openedx.course_experience.course_home', args=[six.text_type(course_key)]))
def reset_course_deadlines(request): """ Set the start_date of a schedule to today, which in turn will adjust due dates for sequentials belonging to a self paced course IMPORTANT NOTE: If updates are happening to the logic here, ALSO UPDATE the `reset_course_deadlines` function in openedx/features/course_experience/api/v1/views.py as well. """ course_key = CourseKey.from_string(request.POST.get('course_id')) _course_masquerade, user = setup_masquerade( request, course_key, has_access(request.user, 'staff', course_key)) missed_deadlines, missed_gated_content = dates_banner_should_display( course_key, user) if missed_deadlines and not missed_gated_content: reset_self_paced_schedule(user, course_key) referrer = request.META.get('HTTP_REFERER') return redirect(referrer) if referrer else HttpResponse()
def reset_course_deadlines(request): """ Set the start_date of a schedule to today, which in turn will adjust due dates for sequentials belonging to a self paced course IMPORTANT NOTE: If updates are happening to the logic here, ALSO UPDATE the `reset_course_deadlines` function in openedx/features/course_experience/api/v1/views.py as well. """ course_key = CourseKey.from_string(request.POST.get('course_id')) _course_masquerade, user = setup_masquerade( request, course_key, has_access(request.user, 'staff', course_key)) # We ignore the missed_deadlines because this endpoint could be used for # learners who have remaining attempts on a problem and reset their due dates in order to # submit additional attempts. This can apply for 'completed' (submitted) content that would # not be marked as past_due _missed_deadlines, missed_gated_content = dates_banner_should_display( course_key, user) if not missed_gated_content: reset_self_paced_schedule(user, course_key) referrer = request.META.get('HTTP_REFERER') return redirect(referrer) if referrer else HttpResponse()
def reset_course_deadlines(request): """ Set the start_date of a schedule to today, which in turn will adjust due dates for sequentials belonging to a self paced course Request Parameters: course_key: course key research_event_data: any data that should be included in the research tracking event Example: sending the location of where the reset deadlines banner (i.e. outline-tab) IMPORTANT NOTE: If updates are happening to the logic here, ALSO UPDATE the `reset_course_deadlines` function in common/djangoapps/util/views.py as well. """ course_key = request.data.get('course_key', None) research_event_data = request.data.get('research_event_data', {}) # If body doesnt contain 'course_key', return 400 to client. if not course_key: raise ParseError(_("'course_key' is required.")) try: course_key = CourseKey.from_string(course_key) course_masquerade, user = setup_masquerade( request, course_key, has_access(request.user, 'staff', course_key)) # We ignore the missed_deadlines because this endpoint is used in the Learning MFE for # learners who have remaining attempts on a problem and reset their due dates in order to # submit additional attempts. This can apply for 'completed' (submitted) content that would # not be marked as past_due _missed_deadlines, missed_gated_content = dates_banner_should_display( course_key, user) if not missed_gated_content: reset_self_paced_schedule(user, course_key) course_overview = course_detail(request, user.username, course_key) # For context here, research_event_data should already contain `location` indicating # the page/location dates were reset from and could also contain `block_id` if reset # within courseware. research_event_data.update({ 'courserun_key': str(course_key), 'is_masquerading': is_masquerading(user, course_key, course_masquerade), 'is_staff': has_access(user, 'staff', course_key).has_access, 'org_key': course_overview.display_org_with_default, 'user_id': user.id, }) tracker.emit('edx.ui.lms.reset_deadlines.clicked', research_event_data) if course_home_legacy_is_active(course_key): body_link = '{}{}'.format(settings.LMS_ROOT_URL, reverse('dates', args=[str(course_key)])) else: body_link = get_learning_mfe_home_url(course_key=str(course_key), view_name='dates') return Response({ 'body': format_html('<a href="{}">{}</a>', body_link, _('View all dates')), 'header': _('Your due dates have been successfully shifted to help you stay on track.' ), 'link': body_link, 'link_text': _('View all dates'), 'message': _('Deadlines successfully reset.'), }) except Exception as reset_deadlines_exception: log.exception('Error occurred while trying to reset deadlines!') raise UnableToResetDeadlines from reset_deadlines_exception