Beispiel #1
0
    def test_is_enabled(self):
        """Verify that is_enabled() returns True when ecomm checkout is enabled. """
        is_enabled = EcommerceService().is_enabled(self.request)
        self.assertTrue(is_enabled)

        config = CommerceConfiguration.current()
        config.checkout_on_ecommerce_service = False
        config.save()
        is_not_enabled = EcommerceService().is_enabled(self.request)
        self.assertFalse(is_not_enabled)
Beispiel #2
0
def program_details(request, program_uuid):
    """View details about a specific program."""
    programs_config = ProgramsApiConfig.current()
    if not programs_config.enabled:
        raise Http404

    meter = ProgramProgressMeter(request.site, request.user, uuid=program_uuid)
    program_data = meter.programs[0]

    if not program_data:
        raise Http404

    program_data = ProgramDataExtender(program_data, request.user).extend()
    course_data = meter.progress(programs=[program_data], count_only=False)[0]
    certificate_data = get_certificates(request.user, program_data)

    program_data.pop('courses')
    skus = program_data.get('skus')
    ecommerce_service = EcommerceService()

    urls = {
        'program_listing_url':
        reverse('program_listing_view'),
        'track_selection_url':
        strip_course_id(
            reverse('course_modes_choose',
                    kwargs={'course_id': FAKE_COURSE_KEY})),
        'commerce_api_url':
        reverse('commerce_api:v0:baskets:create'),
        'buy_button_url':
        ecommerce_service.get_checkout_page_url(*skus)
    }

    context = {
        'urls': urls,
        'show_program_listing': programs_config.enabled,
        'show_dashboard_tabs': True,
        'nav_hidden': True,
        'disable_courseware_js': True,
        'uses_pattern_library': True,
        'user_preferences': get_user_preferences(request.user),
        'program_data': program_data,
        'course_data': course_data,
        'certificate_data': certificate_data
    }

    return render_to_response('learner_dashboard/program_details.html',
                              context)
Beispiel #3
0
    def get_verification_context(self, request, course):
        course_key = CourseKey.from_string(unicode(course.id))

        # Establish whether the course has a verified mode
        available_modes = CourseMode.modes_for_course_dict(unicode(course.id))
        has_verified_mode = CourseMode.has_verified_mode(available_modes)

        # Establish whether the user is already enrolled
        is_already_verified = CourseEnrollment.is_enrolled_as_verified(
            request.user, course_key)

        # Establish whether the verification deadline has already passed
        verification_deadline = VerifiedUpgradeDeadlineDate(
            course, request.user)
        deadline_has_passed = verification_deadline.deadline_has_passed()

        # If this proves its worth, we can internationalize and display for more than English speakers.
        show_course_sock = (has_verified_mode and not is_already_verified
                            and not deadline_has_passed
                            and get_language() == 'en')

        # Get information about the upgrade
        course_price = get_cosmetic_verified_display_price(course)
        upgrade_url = EcommerceService().upgrade_url(request.user, course_key)

        context = {
            'show_course_sock': show_course_sock,
            'course_price': course_price,
            'course_id': course.id,
            'upgrade_url': upgrade_url,
        }

        return context
Beispiel #4
0
 def assert_upgrade_message_displayed(self):
     response = self.client.get(self.url)
     self.assertIn('vc-message', response.content)
     url = EcommerceService().get_checkout_page_url(self.verified_mode.sku)
     expected = '<a class="btn-upgrade" href="{url}">Upgrade (${price})</a>'.format(
         url=url, price=self.verified_mode.min_price)
     self.assertIn(expected, response.content)
Beispiel #5
0
 def test_get_receipt_page_url(self):
     """Verify that the proper Receipt page URL is returned."""
     order_number = 'ORDER1'
     url = EcommerceService().get_receipt_page_url(order_number)
     expected_url = 'http://ecommerce_url/checkout/receipt/?order_number={}'.format(
         order_number)
     self.assertEqual(url, expected_url)
Beispiel #6
0
 def test_get_checkout_page_url(self, skus):
     """ Verify the checkout page URL is properly constructed and returned. """
     url = EcommerceService().get_checkout_page_url(*skus)
     expected_url = '{root}/test_basket/?{skus}'.format(
         root=settings.ECOMMERCE_PUBLIC_URL_ROOT,
         skus=urlencode({'sku': skus}, doseq=True),
     )
     self.assertEqual(url, expected_url)
 def assert_upgrade_message_displayed(self):
     response = self.client.get(self.url)
     self.assertIn('vc-message', response.content)
     url = EcommerceService().get_checkout_page_url(self.verified_mode.sku)
     self.assertIn('<a class="btn btn-upgrade"', response.content)
     self.assertIn(url, response.content)
     self.assertIn(
         'Upgrade (${price})</a>'.format(
             price=self.verified_mode.min_price), response.content)
Beispiel #8
0
def program_details(request, program_uuid):
    """View details about a specific program."""
    programs_config = ProgramsApiConfig.current()
    if not programs_config.enabled:
        raise Http404

    meter = ProgramProgressMeter(request.site, request.user, uuid=program_uuid)
    program_data = meter.programs[0]

    if not program_data:
        raise Http404

    program_data = ProgramDataExtender(program_data, request.user).extend()
    course_data = meter.progress(programs=[program_data], count_only=False)[0]
    certificate_data = get_certificates(request.user, program_data)

    program_data.pop('courses')
    skus = program_data.get('skus')
    ecommerce_service = EcommerceService()

    urls = {
        'program_listing_url': reverse('program_listing_view'),
        'track_selection_url': strip_course_id(
            reverse('course_modes_choose', kwargs={'course_id': FAKE_COURSE_KEY})
        ),
        'commerce_api_url': reverse('commerce_api:v0:baskets:create'),
        'buy_button_url': ecommerce_service.get_checkout_page_url(*skus)
    }

    context = {
        'urls': urls,
        'show_program_listing': programs_config.enabled,
        'show_dashboard_tabs': True,
        'nav_hidden': True,
        'disable_courseware_js': True,
        'uses_pattern_library': True,
        'user_preferences': get_user_preferences(request.user),
        'program_data': program_data,
        'course_data': course_data,
        'certificate_data': certificate_data
    }

    return render_to_response('learner_dashboard/program_details.html', context)
Beispiel #9
0
    def test_get_receipt_page_url_with_site_configuration(self):
        order_number = 'ORDER1'
        config = CommerceConfiguration.current()
        config.use_ecommerce_receipt_page = True
        config.save()

        receipt_page_url = EcommerceService().get_receipt_page_url(
            order_number)
        expected_url = '{ecommerce_root}{receipt_page_url}{order_number}'.format(
            ecommerce_root=settings.ECOMMERCE_PUBLIC_URL_ROOT,
            order_number=order_number,
            receipt_page_url=TEST_SITE_CONFIGURATION[
                'ECOMMERCE_RECEIPT_PAGE_URL'])
        self.assertEqual(receipt_page_url, expected_url)
Beispiel #10
0
    def _redirect_if_necessary(
            self,
            message,
            already_verified,
            already_paid,
            is_enrolled,
            course_key,  # pylint: disable=bad-continuation
            user_is_trying_to_pay,
            user,
            sku  # pylint: disable=bad-continuation
    ):
        """Redirect the user to a more appropriate page if necessary.

        In some cases, a user may visit this page with
        verification / enrollment / payment state that
        we don't anticipate.  For example, a user may unenroll
        from the course after paying for it, then visit the
        "verify now" page to complete verification.

        When this happens, we try to redirect the user to
        the most appropriate page.

        Arguments:

            message (string): The messaging of the page.  Should be a key
                in `MESSAGES`.

            already_verified (bool): Whether the user has submitted
                a verification request recently.

            already_paid (bool): Whether the user is enrolled in a paid
                course mode.

            is_enrolled (bool): Whether the user has an active enrollment
                in the course.

            course_key (CourseKey): The key for the course.

        Returns:
            HttpResponse or None

        """
        url = None
        course_kwargs = {'course_id': unicode(course_key)}

        if already_verified and already_paid:
            # If they've already paid and verified, there's nothing else to do,
            # so redirect them to the dashboard.
            if message != self.PAYMENT_CONFIRMATION_MSG:
                url = reverse('dashboard')
        elif message in [
                self.VERIFY_NOW_MSG, self.VERIFY_LATER_MSG,
                self.PAYMENT_CONFIRMATION_MSG
        ]:
            if is_enrolled:
                # If the user is already enrolled but hasn't yet paid,
                # then the "upgrade" messaging is more appropriate.
                if not already_paid:
                    url = reverse('verify_student_upgrade_and_verify',
                                  kwargs=course_kwargs)
            else:
                # If the user is NOT enrolled, then send him/her
                # to the first time verification page.
                url = reverse('verify_student_start_flow',
                              kwargs=course_kwargs)
        elif message == self.UPGRADE_MSG:
            if is_enrolled:
                if already_paid:
                    # If the student has paid, but not verified, redirect to the verification flow.
                    url = reverse('verify_student_verify_now',
                                  kwargs=course_kwargs)
            else:
                url = reverse('verify_student_start_flow',
                              kwargs=course_kwargs)

        if user_is_trying_to_pay and self._get_user_active_status(
                user) and not already_paid:
            # If the user is trying to pay, has activated their account, and the ecommerce service
            # is enabled redirect him to the ecommerce checkout page.
            ecommerce_service = EcommerceService()
            if ecommerce_service.is_enabled(user):
                url = ecommerce_service.checkout_page_url(sku)

        # Redirect if necessary, otherwise implicitly return None
        if url is not None:
            return redirect(url)
Beispiel #11
0
    def render_to_fragment(self, request, course_id=None, **kwargs):
        """
        Renders the course's home page as a fragment.
        """
        course_key = CourseKey.from_string(course_id)
        course = get_course_with_access(request.user, 'load', course_key)

        # Render the course dates as a fragment
        dates_fragment = CourseDatesFragmentView().render_to_fragment(request, course_id=course_id, **kwargs)

        # Render the full content to enrolled users, as well as to course and global staff.
        # Unenrolled users who are not course or global staff are given only a subset.
        enrollment = CourseEnrollment.get_enrollment(request.user, course_key)
        user_access = {
            'is_anonymous': request.user.is_anonymous(),
            'is_enrolled': enrollment is not None,
            'is_staff': has_access(request.user, 'staff', course_key),
        }
        if user_access['is_enrolled'] or user_access['is_staff']:
            outline_fragment = CourseOutlineFragmentView().render_to_fragment(request, course_id=course_id, **kwargs)
            if LATEST_UPDATE_FLAG.is_enabled(course_key):
                update_message_fragment = LatestUpdateFragmentView().render_to_fragment(
                    request, course_id=course_id, **kwargs
                )
            else:
                update_message_fragment = WelcomeMessageFragmentView().render_to_fragment(
                    request, course_id=course_id, **kwargs
                )
            course_sock_fragment = CourseSockFragmentView().render_to_fragment(request, course=course, **kwargs)
            has_visited_course, resume_course_url = self._get_resume_course_info(request, course_id)
        else:
            # Redirect the user to the dashboard if they are not enrolled and
            # this is a course that does not support direct enrollment.
            if not can_self_enroll_in_course(course_key):
                raise CourseAccessRedirect(reverse('dashboard'))

            # Set all the fragments
            outline_fragment = None
            update_message_fragment = None
            course_sock_fragment = None
            has_visited_course = None
            resume_course_url = None

        # Get the handouts
        handouts_html = self._get_course_handouts(request, course)

        # Get the course tools enabled for this user and course
        course_tools = CourseToolsPluginManager.get_enabled_course_tools(request, course_key)

        # Check if the user can access the course goal functionality
        has_goal_permission = has_course_goal_permission(request, course_id, user_access)

        # Grab the current course goal and the acceptable course goal keys mapped to translated values
        current_goal = get_course_goal(request.user, course_key)
        goal_options = get_course_goal_options()

        # Get the course goals api endpoint
        goal_api_url = get_goal_api_url(request)

        # Grab the course home messages fragment to render any relevant django messages
        course_home_message_fragment = CourseHomeMessageFragmentView().render_to_fragment(
            request, course_id=course_id, user_access=user_access, **kwargs
        )

        # Get info for upgrade messaging
        upgrade_price = None
        upgrade_url = None

        # TODO Add switch to control deployment
        if SHOW_UPGRADE_MSG_ON_COURSE_HOME.is_enabled(course_key) and enrollment and enrollment.upgrade_deadline:
            upgrade_url = EcommerceService().upgrade_url(request.user, course_key)
            upgrade_price = get_cosmetic_verified_display_price(course)

        # Render the course home fragment
        context = {
            'request': request,
            'csrf': csrf(request)['csrf_token'],
            'course': course,
            'course_key': course_key,
            'outline_fragment': outline_fragment,
            'handouts_html': handouts_html,
            'course_home_message_fragment': course_home_message_fragment,
            'has_visited_course': has_visited_course,
            'resume_course_url': resume_course_url,
            'course_tools': course_tools,
            'dates_fragment': dates_fragment,
            'username': request.user.username,
            'goal_api_url': goal_api_url,
            'has_goal_permission': has_goal_permission,
            'goal_options': goal_options,
            'current_goal': current_goal,
            'update_message_fragment': update_message_fragment,
            'course_sock_fragment': course_sock_fragment,
            'disable_courseware_js': True,
            'uses_pattern_library': True,
            'upgrade_price': upgrade_price,
            'upgrade_url': upgrade_url,
        }
        html = render_to_string('course_experience/course-home-fragment.html', context)
        return Fragment(html)
Beispiel #12
0
    def _redirect_if_necessary(
            self, message, already_verified, already_paid, is_enrolled, course_key,  # pylint: disable=bad-continuation
            user_is_trying_to_pay, user, sku  # pylint: disable=bad-continuation
    ):
        """Redirect the user to a more appropriate page if necessary.

        In some cases, a user may visit this page with
        verification / enrollment / payment state that
        we don't anticipate.  For example, a user may unenroll
        from the course after paying for it, then visit the
        "verify now" page to complete verification.

        When this happens, we try to redirect the user to
        the most appropriate page.

        Arguments:

            message (string): The messaging of the page.  Should be a key
                in `MESSAGES`.

            already_verified (bool): Whether the user has submitted
                a verification request recently.

            already_paid (bool): Whether the user is enrolled in a paid
                course mode.

            is_enrolled (bool): Whether the user has an active enrollment
                in the course.

            course_key (CourseKey): The key for the course.

        Returns:
            HttpResponse or None

        """
        url = None
        course_kwargs = {'course_id': unicode(course_key)}

        if already_verified and already_paid:
            # If they've already paid and verified, there's nothing else to do,
            # so redirect them to the dashboard.
            if message != self.PAYMENT_CONFIRMATION_MSG:
                url = reverse('dashboard')
        elif message in [self.VERIFY_NOW_MSG, self.VERIFY_LATER_MSG, self.PAYMENT_CONFIRMATION_MSG]:
            if is_enrolled:
                # If the user is already enrolled but hasn't yet paid,
                # then the "upgrade" messaging is more appropriate.
                if not already_paid:
                    url = reverse('verify_student_upgrade_and_verify', kwargs=course_kwargs)
            else:
                # If the user is NOT enrolled, then send him/her
                # to the first time verification page.
                url = reverse('verify_student_start_flow', kwargs=course_kwargs)
        elif message == self.UPGRADE_MSG:
            if is_enrolled:
                if already_paid:
                    # If the student has paid, but not verified, redirect to the verification flow.
                    url = reverse('verify_student_verify_now', kwargs=course_kwargs)
            else:
                url = reverse('verify_student_start_flow', kwargs=course_kwargs)

        if user_is_trying_to_pay and self._get_user_active_status(user) and not already_paid:
            # If the user is trying to pay, has activated their account, and the ecommerce service
            # is enabled redirect him to the ecommerce checkout page.
            ecommerce_service = EcommerceService()
            if ecommerce_service.is_enabled(user):
                url = ecommerce_service.get_checkout_page_url(sku)

        # Redirect if necessary, otherwise implicitly return None
        if url is not None:
            return redirect(url)
Beispiel #13
0
 def test_checkout_page_url(self):
     """ Verify the checkout page URL is properly constructed and returned. """
     url = EcommerceService().checkout_page_url(self.SKU)
     expected_url = 'http://ecommerce_url/test_basket/?sku={}'.format(self.SKU)
     self.assertEqual(url, expected_url)
Beispiel #14
0
 def test_payment_page_url(self):
     """Verify that the proper URL is returned."""
     url = EcommerceService().payment_page_url()
     self.assertEqual(url, 'http://ecommerce_url/test_basket/')
Beispiel #15
0
 def test_is_enabled_for_microsites(self, is_microsite):
     """Verify that is_enabled() returns False if used for a microsite."""
     is_microsite.return_value = True
     is_not_enabled = EcommerceService().is_enabled(self.request)
     self.assertFalse(is_not_enabled)
Beispiel #16
0
 def test_is_enabled_activation_requirement_disabled(self):
     """Verify that is_enabled() returns True when ecomm checkout is enabled. """
     self.user.is_active = False
     self.user.save()
     is_enabled = EcommerceService().is_enabled(self.user)
     self.assertTrue(is_enabled)
    def render_to_fragment(self, request, course_id=None, **kwargs):
        """
        Renders the course's home page as a fragment.
        """
        course_key = CourseKey.from_string(course_id)
        course = get_course_with_access(request.user, 'load', course_key)

        # Render the course dates as a fragment
        dates_fragment = CourseDatesFragmentView().render_to_fragment(request, course_id=course_id, **kwargs)

        # Render the full content to enrolled users, as well as to course and global staff.
        # Unenrolled users who are not course or global staff are given only a subset.
        enrollment = CourseEnrollment.get_enrollment(request.user, course_key)
        user_access = {
            'is_anonymous': request.user.is_anonymous(),
            'is_enrolled': enrollment is not None,
            'is_staff': has_access(request.user, 'staff', course_key),
        }
        if user_access['is_enrolled'] or user_access['is_staff']:
            outline_fragment = CourseOutlineFragmentView().render_to_fragment(request, course_id=course_id, **kwargs)
            if LATEST_UPDATE_FLAG.is_enabled(course_key):
                update_message_fragment = LatestUpdateFragmentView().render_to_fragment(
                    request, course_id=course_id, **kwargs
                )
            else:
                update_message_fragment = WelcomeMessageFragmentView().render_to_fragment(
                    request, course_id=course_id, **kwargs
                )
            course_sock_fragment = CourseSockFragmentView().render_to_fragment(request, course=course, **kwargs)
            has_visited_course, resume_course_url = self._get_resume_course_info(request, course_id)
        else:
            # Redirect the user to the dashboard if they are not enrolled and
            # this is a course that does not support direct enrollment.
            if not can_self_enroll_in_course(course_key):
                raise CourseAccessRedirect(reverse('dashboard'))

            # Set all the fragments
            outline_fragment = None
            update_message_fragment = None
            course_sock_fragment = None
            has_visited_course = None
            resume_course_url = None

        # Get the handouts
        handouts_html = self._get_course_handouts(request, course)

        # Get the course tools enabled for this user and course
        course_tools = CourseToolsPluginManager.get_enabled_course_tools(request, course_key)

        # Grab the course home messages fragment to render any relevant django messages
        course_home_message_fragment = CourseHomeMessageFragmentView().render_to_fragment(
            request, course_id=course_id, user_access=user_access, **kwargs
        )

        # Get info for upgrade messaging
        upgrade_price = None
        upgrade_url = None

        # TODO Add switch to control deployment
        if SHOW_UPGRADE_MSG_ON_COURSE_HOME.is_enabled(course_key) and enrollment and enrollment.upgrade_deadline:
            verified_mode = enrollment.verified_mode
            if verified_mode:
                upgrade_price = verified_mode.min_price

                ecommerce_service = EcommerceService()
                if ecommerce_service.is_enabled(request.user):
                    upgrade_url = ecommerce_service.get_checkout_page_url(verified_mode.sku)
                else:
                    upgrade_url = reverse('verify_student_upgrade_and_verify', args=(course_key,))

        # Render the course home fragment
        context = {
            'request': request,
            'csrf': csrf(request)['csrf_token'],
            'course': course,
            'course_key': course_key,
            'outline_fragment': outline_fragment,
            'handouts_html': handouts_html,
            'course_home_message_fragment': course_home_message_fragment,
            'has_visited_course': has_visited_course,
            'resume_course_url': resume_course_url,
            'course_tools': course_tools,
            'dates_fragment': dates_fragment,
            'update_message_fragment': update_message_fragment,
            'course_sock_fragment': course_sock_fragment,
            'disable_courseware_js': True,
            'uses_pattern_library': True,
            'upgrade_price': upgrade_price,
            'upgrade_url': upgrade_url,
        }
        html = render_to_string('course_experience/course-home-fragment.html', context)
        return Fragment(html)
Beispiel #18
0
 def test_get_absolute_ecommerce_url(self):
     """Verify that the proper URL is returned."""
     url = EcommerceService().get_absolute_ecommerce_url('/test_basket/')
     self.assertEqual(url, 'http://ecommerce_url/test_basket/')
Beispiel #19
0
 def test_ecommerce_url_root(self):
     """Verify that the proper root URL is returned."""
     self.assertEqual(EcommerceService().ecommerce_url_root,
                      'http://ecommerce_url')