Ejemplo n.º 1
0
    def test_generate_course_expired_message(self, offsets):
        now = timezone.now()
        schedule_offset, course_offset = offsets

        # Set a timezone and request, to test that the message looks at the user's setting
        request = RequestFactory().get('/')
        request.user = UserFactory()
        set_current_request(request)
        self.addCleanup(set_current_request, None)
        set_user_preference(request.user, 'time_zone', 'Asia/Tokyo')

        if schedule_offset is not None:
            schedule_upgrade_deadline = now + timedelta(days=schedule_offset)
        else:
            schedule_upgrade_deadline = None

        if course_offset is not None:
            course_upgrade_deadline = now + timedelta(days=course_offset)
        else:
            course_upgrade_deadline = None

        enrollment = CourseEnrollmentFactory.create(
            course__start=datetime(2018, 1, 1, tzinfo=UTC),
            course__self_paced=True,
        )
        CourseModeFactory.create(
            course_id=enrollment.course.id,
            mode_slug=CourseMode.VERIFIED,
            expiration_datetime=course_upgrade_deadline,
        )
        CourseModeFactory.create(
            course_id=enrollment.course.id,
            mode_slug=CourseMode.AUDIT,
        )
        ScheduleFactory.create(
            enrollment=enrollment,
            upgrade_deadline=schedule_upgrade_deadline,
        )

        duration_limit_upgrade_deadline = get_user_course_expiration_date(
            enrollment.user, enrollment.course)
        self.assertIsNotNone(duration_limit_upgrade_deadline)

        message = generate_course_expired_message(enrollment.user,
                                                  enrollment.course)

        self.assertDateInMessage(duration_limit_upgrade_deadline, message)
        self.assertIn('data-timezone="Asia/Tokyo"', message)

        soft_upgradeable = schedule_upgrade_deadline is not None and now < schedule_upgrade_deadline
        upgradeable = course_upgrade_deadline is None or now < course_upgrade_deadline
        has_upgrade_deadline = course_upgrade_deadline is not None

        if upgradeable and soft_upgradeable:
            self.assertDateInMessage(schedule_upgrade_deadline, message)
        elif upgradeable and has_upgrade_deadline:
            self.assertDateInMessage(course_upgrade_deadline, message)
        else:
            self.assertNotIn("Upgrade by", message)
Ejemplo n.º 2
0
    def test_generate_course_expired_message(self, offsets):
        now = timezone.now()
        schedule_offset, course_offset = offsets

        if schedule_offset is not None:
            schedule_upgrade_deadline = now + timedelta(days=schedule_offset)
        else:
            schedule_upgrade_deadline = None

        if course_offset is not None:
            course_upgrade_deadline = now + timedelta(days=course_offset)
        else:
            course_upgrade_deadline = None

        def format_date(date):
            return strftime_localized(date, u'%b %-d, %Y')

        enrollment = CourseEnrollmentFactory.create(
            course__start=datetime(2018, 1, 1, tzinfo=UTC),
            course__self_paced=True,
        )
        CourseModeFactory.create(
            course_id=enrollment.course.id,
            mode_slug=CourseMode.VERIFIED,
            expiration_datetime=course_upgrade_deadline,
        )
        CourseModeFactory.create(
            course_id=enrollment.course.id,
            mode_slug=CourseMode.AUDIT,
        )
        ScheduleFactory.create(
            enrollment=enrollment,
            upgrade_deadline=schedule_upgrade_deadline,
        )

        duration_limit_upgrade_deadline = get_user_course_expiration_date(
            enrollment.user, enrollment.course)
        self.assertIsNotNone(duration_limit_upgrade_deadline)

        message = generate_course_expired_message(enrollment.user,
                                                  enrollment.course)

        self.assertIn(format_date(duration_limit_upgrade_deadline), message)

        soft_upgradeable = schedule_upgrade_deadline is not None and now < schedule_upgrade_deadline
        upgradeable = course_upgrade_deadline is None or now < course_upgrade_deadline
        has_upgrade_deadline = course_upgrade_deadline is not None

        if upgradeable and soft_upgradeable:
            self.assertIn(format_date(schedule_upgrade_deadline), message)
        elif upgradeable and has_upgrade_deadline:
            self.assertIn(format_date(course_upgrade_deadline), message)
        else:
            self.assertNotIn("Upgrade by", message)
Ejemplo n.º 3
0
    def test_generate_course_expired_message(self, offsets):
        now = timezone.now()
        schedule_offset, course_offset = offsets

        if schedule_offset is not None:
            schedule_upgrade_deadline = now + timedelta(days=schedule_offset)
        else:
            schedule_upgrade_deadline = None

        if course_offset is not None:
            course_upgrade_deadline = now + timedelta(days=course_offset)
        else:
            course_upgrade_deadline = None

        def format_date(date):
            return strftime_localized(date, u'%b %-d, %Y')

        enrollment = CourseEnrollmentFactory.create(
            course__start=datetime(2018, 1, 1, tzinfo=UTC),
            course__self_paced=True,
        )
        CourseModeFactory.create(
            course_id=enrollment.course.id,
            mode_slug=CourseMode.VERIFIED,
            expiration_datetime=course_upgrade_deadline,
        )
        CourseModeFactory.create(
            course_id=enrollment.course.id,
            mode_slug=CourseMode.AUDIT,
        )
        ScheduleFactory.create(
            enrollment=enrollment,
            upgrade_deadline=schedule_upgrade_deadline,
        )

        duration_limit_upgrade_deadline = get_user_course_expiration_date(enrollment.user, enrollment.course)
        self.assertIsNotNone(duration_limit_upgrade_deadline)

        message = generate_course_expired_message(enrollment.user, enrollment.course)

        self.assertIn(format_date(duration_limit_upgrade_deadline), message)

        soft_upgradeable = schedule_upgrade_deadline is not None and now < schedule_upgrade_deadline
        upgradeable = course_upgrade_deadline is None or now < course_upgrade_deadline
        has_upgrade_deadline = course_upgrade_deadline is not None

        if upgradeable and soft_upgradeable:
            self.assertIn(format_date(schedule_upgrade_deadline), message)
        elif upgradeable and has_upgrade_deadline:
            self.assertIn(format_date(course_upgrade_deadline), message)
        else:
            self.assertNotIn("Upgrade by", message)
Ejemplo n.º 4
0
    def get_object(self):
        """
        Return the requested course object, if the user has appropriate
        permissions.
        """

        overview = course_detail(
            self.request,
            self.request.user.username,
            CourseKey.from_string(self.kwargs['course_key_string']),
        )

        if self.request.user.is_anonymous:
            mode = None
            is_active = False
        else:
            mode, is_active = CourseEnrollment.enrollment_mode_for_user(
                overview.effective_user, overview.id)
        overview.enrollment = {'mode': mode, 'is_active': is_active}

        overview.is_staff = has_access(self.request.user, 'staff',
                                       overview).has_access
        overview.can_load_courseware = check_course_access(
            overview,
            self.request.user,
            'load',
            check_if_enrolled=True,
            check_survey_complete=False,
            check_if_authenticated=True,
        ).to_json()

        # TODO: TNL-7185 Legacy: Refactor to return the expiration date and format the message in the MFE
        overview.course_expired_message = generate_course_expired_message(
            self.request.user, overview)
        # TODO: TNL-7185 Legacy: Refactor to return the offer data and format the message in the MFE
        overview.offer_html = generate_offer_html(self.request.user, overview)

        course_key = CourseKey.from_string(self.kwargs['course_key_string'])
        overview.content_type_gating_enabled = ContentTypeGatingConfig.enabled_for_enrollment(
            user=self.request.user,
            course_key=course_key,
        )
        return overview
Ejemplo n.º 5
0
 def course_expired_message(self):
     # TODO: TNL-7185 Legacy: Refactor to return the expiration date and format the message in the MFE
     return generate_course_expired_message(self.effective_user,
                                            self.overview)
Ejemplo n.º 6
0
    def get(self, request, *args, **kwargs):
        course_key_string = kwargs.get('course_key_string')
        course_key = CourseKey.from_string(course_key_string)
        course_usage_key = modulestore().make_course_usage_key(course_key)

        if not course_home_mfe_outline_tab_is_active(course_key):
            raise Http404

        # Enable NR tracing for this view based on course
        monitoring_utils.set_custom_metric('course_id', course_key_string)
        monitoring_utils.set_custom_metric('user_id', request.user.id)
        monitoring_utils.set_custom_metric('is_staff', request.user.is_staff)

        course = get_course_with_access(request.user,
                                        'load',
                                        course_key,
                                        check_if_enrolled=False)

        _masquerade, request.user = setup_masquerade(
            request,
            course_key,
            staff_access=has_access(request.user, 'staff', course_key),
            reset_masquerade_data=True,
        )

        course_overview = CourseOverview.get_from_id(course_key)
        enrollment = CourseEnrollment.get_enrollment(request.user, course_key)
        allow_anonymous = COURSE_ENABLE_UNENROLLED_ACCESS_FLAG.is_enabled(
            course_key)
        allow_public = allow_anonymous and course.course_visibility == COURSE_VISIBILITY_PUBLIC
        is_enrolled = enrollment and enrollment.is_active
        is_staff = has_access(request.user, 'staff', course_key)
        show_enrolled = is_enrolled or is_staff

        show_handouts = show_enrolled or allow_public
        handouts_html = get_course_info_section(
            request, request.user, course, 'handouts') if show_handouts else ''

        # TODO: TNL-7185 Legacy: Refactor to return the offer & expired data and format the message in the MFE
        offer_html = generate_offer_html(request.user, course_overview)
        course_expired_html = generate_course_expired_message(
            request.user, course_overview)

        welcome_message_html = None
        if get_course_tag(request.user, course_key, PREFERENCE_KEY) != 'False':
            if LATEST_UPDATE_FLAG.is_enabled(course_key):
                welcome_message_html = LatestUpdateFragmentView(
                ).latest_update_html(request, course)
            else:
                welcome_message_html = WelcomeMessageFragmentView(
                ).welcome_message_html(request, course)

        enroll_alert = {
            'can_enroll': True,
            'extra_text': None,
        }
        if not show_enrolled:
            if CourseMode.is_masters_only(course_key):
                enroll_alert['can_enroll'] = False
                enroll_alert['extra_text'] = _(
                    'Please contact your degree administrator or '
                    'edX Support if you have questions.')
            elif course.invitation_only:
                enroll_alert['can_enroll'] = False

        course_tools = CourseToolsPluginManager.get_enabled_course_tools(
            request, course_key)
        date_blocks = get_course_date_blocks(course,
                                             request.user,
                                             request,
                                             num_assignments=1)

        # User locale settings
        user_timezone_locale = user_timezone_locale_prefs(request)
        user_timezone = user_timezone_locale['user_timezone']

        dates_tab_link = request.build_absolute_uri(
            reverse('dates', args=[course.id]))
        if course_home_mfe_dates_tab_is_active(course.id):
            dates_tab_link = get_microfrontend_url(course_key=course.id,
                                                   view_name='dates')

        transformers = BlockStructureTransformers()
        transformers += get_course_block_access_transformers(request.user)
        transformers += [
            BlocksAPITransformer(None, None, depth=3),
        ]

        course_blocks = get_course_blocks(request.user,
                                          course_usage_key,
                                          transformers,
                                          include_completion=True)

        dates_widget = {
            'course_date_blocks': [
                block for block in date_blocks
                if not isinstance(block, TodaysDate)
            ],
            'dates_tab_link':
            dates_tab_link,
            'user_timezone':
            user_timezone,
        }

        data = {
            'course_blocks': course_blocks,
            'course_expired_html': course_expired_html,
            'course_tools': course_tools,
            'dates_widget': dates_widget,
            'enroll_alert': enroll_alert,
            'handouts_html': handouts_html,
            'offer_html': offer_html,
            'welcome_message_html': welcome_message_html,
        }
        context = self.get_serializer_context()
        context['course_key'] = course_key
        serializer = self.get_serializer_class()(data, context=context)

        return Response(serializer.data)
Ejemplo n.º 7
0
    def get(self, request, *args, **kwargs):
        course_key_string = kwargs.get('course_key_string')
        course_key = CourseKey.from_string(course_key_string)
        course_usage_key = modulestore().make_course_usage_key(course_key)

        if not course_home_mfe_outline_tab_is_active(course_key):
            raise Http404

        # Enable NR tracing for this view based on course
        monitoring_utils.set_custom_attribute('course_id', course_key_string)
        monitoring_utils.set_custom_attribute('user_id', request.user.id)
        monitoring_utils.set_custom_attribute('is_staff',
                                              request.user.is_staff)

        course = get_course_with_access(request.user,
                                        'load',
                                        course_key,
                                        check_if_enrolled=False)

        _masquerade, request.user = setup_masquerade(
            request,
            course_key,
            staff_access=has_access(request.user, 'staff', course_key),
            reset_masquerade_data=True,
        )

        course_overview = CourseOverview.get_from_id(course_key)
        enrollment = CourseEnrollment.get_enrollment(request.user, course_key)
        allow_anonymous = COURSE_ENABLE_UNENROLLED_ACCESS_FLAG.is_enabled(
            course_key)
        allow_public = allow_anonymous and course.course_visibility == COURSE_VISIBILITY_PUBLIC
        allow_public_outline = allow_anonymous and course.course_visibility == COURSE_VISIBILITY_PUBLIC_OUTLINE
        is_enrolled = enrollment and enrollment.is_active
        is_staff = bool(has_access(request.user, 'staff', course_key))
        show_enrolled = is_enrolled or is_staff

        show_handouts = show_enrolled or allow_public
        handouts_html = get_course_info_section(
            request, request.user, course, 'handouts') if show_handouts else ''

        # TODO: TNL-7185 Legacy: Refactor to return the offer & expired data and format the message in the MFE
        offer_html = show_enrolled and generate_offer_html(
            request.user, course_overview)
        course_expired_html = show_enrolled and generate_course_expired_message(
            request.user, course_overview)

        welcome_message_html = None
        if show_enrolled:
            if LATEST_UPDATE_FLAG.is_enabled(course_key):
                welcome_message_html = LatestUpdateFragmentView(
                ).latest_update_html(request, course)
            elif get_course_tag(request.user, course_key,
                                PREFERENCE_KEY) != 'False':
                welcome_message_html = WelcomeMessageFragmentView(
                ).welcome_message_html(request, course)

        enroll_alert = {
            'can_enroll': True,
            'extra_text': None,
        }
        if not show_enrolled:
            if CourseMode.is_masters_only(course_key):
                enroll_alert['can_enroll'] = False
                enroll_alert['extra_text'] = _(
                    'Please contact your degree administrator or '
                    'edX Support if you have questions.')
            elif course.invitation_only:
                enroll_alert['can_enroll'] = False

        course_tools = CourseToolsPluginManager.get_enabled_course_tools(
            request, course_key)
        date_blocks = get_course_date_blocks(course,
                                             request.user,
                                             request,
                                             num_assignments=1)

        # User locale settings
        user_timezone_locale = user_timezone_locale_prefs(request)
        user_timezone = user_timezone_locale['user_timezone']

        dates_tab_link = request.build_absolute_uri(
            reverse('dates', args=[course.id]))
        if course_home_mfe_dates_tab_is_active(course.id):
            dates_tab_link = get_microfrontend_url(course_key=course.id,
                                                   view_name='dates')

        course_blocks = None
        if show_enrolled or allow_public or allow_public_outline:
            outline_user = request.user if show_enrolled else None
            course_blocks = get_course_outline_block_tree(
                request, course_key_string, outline_user)

        resume_course = {
            'has_visited_course': False,
            'url': None,
        }
        if show_enrolled:
            try:
                resume_block = get_key_to_last_completed_block(
                    request.user, course.id)
                resume_course['has_visited_course'] = True
            except UnavailableCompletionData:
                resume_block = course_usage_key
            resume_path = reverse('jump_to',
                                  kwargs={
                                      'course_id': course_key_string,
                                      'location': str(resume_block)
                                  })
            resume_course['url'] = request.build_absolute_uri(resume_path)

        dates_widget = {
            'course_date_blocks': [
                block for block in date_blocks
                if not isinstance(block, TodaysDate)
            ],
            'dates_tab_link':
            dates_tab_link,
            'user_timezone':
            user_timezone,
        }

        # Only show the set course goal message for enrolled, unverified
        # users in a course that allows for verified statuses.
        is_already_verified = CourseEnrollment.is_enrolled_as_verified(
            request.user, course_key)
        if (not is_already_verified and has_course_goal_permission(
                request, course_key_string, {'is_enrolled': is_enrolled})):
            course_goals = {
                'goal_options':
                valid_course_goals_ordered(include_unsure=True),
                'selected_goal': None
            }

            selected_goal = get_course_goal(request.user, course_key)
            if selected_goal:
                course_goals['selected_goal'] = {
                    'key': selected_goal.goal_key,
                    'text': get_course_goal_text(selected_goal.goal_key),
                }
        else:
            course_goals = {'goal_options': [], 'selected_goal': None}

        data = {
            'course_blocks': course_blocks,
            'course_expired_html': course_expired_html or None,
            'course_goals': course_goals,
            'course_tools': course_tools,
            'dates_widget': dates_widget,
            'enroll_alert': enroll_alert,
            'handouts_html': handouts_html or None,
            'has_ended': course.has_ended(),
            'offer_html': offer_html or None,
            'resume_course': resume_course,
            'welcome_message_html': welcome_message_html or None,
        }
        context = self.get_serializer_context()
        context['course_key'] = course_key
        context['enable_links'] = show_enrolled or allow_public
        serializer = self.get_serializer_class()(data, context=context)

        return Response(serializer.data)
Ejemplo n.º 8
0
    def test_generate_course_expired_message(self, language, offsets):
        now = timezone.now()
        schedule_offset, course_offset = offsets

        if schedule_offset is not None:
            schedule_upgrade_deadline = now + timedelta(days=schedule_offset)
        else:
            schedule_upgrade_deadline = None

        if course_offset is not None:
            course_upgrade_deadline = now + timedelta(days=course_offset)
        else:
            course_upgrade_deadline = None

        def format_date(date):
            if language.startswith('es-'):
                return strftime_localized(date, '%-d de %b. de %Y').lower()
            else:
                return strftime_localized(date, '%b. %-d, %Y')

        patch_lang = patch(
            'openedx.features.course_duration_limits.access.get_language',
            return_value=language)
        with patch_lang:
            enrollment = CourseEnrollmentFactory.create(
                course__start=datetime(2018, 1, 1, tzinfo=UTC),
                course__self_paced=True,
            )
            CourseModeFactory.create(
                course_id=enrollment.course.id,
                mode_slug=CourseMode.VERIFIED,
                expiration_datetime=course_upgrade_deadline,
            )
            CourseModeFactory.create(
                course_id=enrollment.course.id,
                mode_slug=CourseMode.AUDIT,
            )
            ScheduleFactory.create(
                enrollment=enrollment,
                upgrade_deadline=schedule_upgrade_deadline,
            )

            duration_limit_upgrade_deadline = get_user_course_expiration_date(
                enrollment.user, enrollment.course)
            self.assertIsNotNone(duration_limit_upgrade_deadline)

            message = generate_course_expired_message(enrollment.user,
                                                      enrollment.course)

            self.assertIn(format_date(duration_limit_upgrade_deadline),
                          message)

            soft_upgradeable = schedule_upgrade_deadline is not None and now < schedule_upgrade_deadline
            upgradeable = course_upgrade_deadline is None or now < course_upgrade_deadline
            has_upgrade_deadline = course_upgrade_deadline is not None

            if upgradeable and soft_upgradeable:
                self.assertIn(format_date(schedule_upgrade_deadline), message)
            elif upgradeable and has_upgrade_deadline:
                self.assertIn(format_date(course_upgrade_deadline), message)
            else:
                self.assertNotIn("Upgrade by", message)