views.py 6.14 KB
Newer Older
1 2 3 4
"""
Views for the course_mode module
"""

5
import decimal
6
from django.core.urlresolvers import reverse
7
from django.http import HttpResponseBadRequest
8
from django.shortcuts import redirect
9
from django.views.generic.base import View
10
from django.utils.translation import ugettext as _
11 12
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
13

David Baumgold committed
14
from edxmako.shortcuts import render_to_response
15 16

from course_modes.models import CourseMode
17
from courseware.access import has_access
Julia Hansbrough committed
18
from student.models import CourseEnrollment
19
from verify_student.models import SoftwareSecurePhotoVerification
20
from opaque_keys.edx.locations import SlashSeparatedCourseKey
21
from xmodule.modulestore.django import modulestore
22 23


24 25 26 27 28 29 30 31 32
class ChooseModeView(View):
    """
    View used when the user is asked to pick a mode

    When a get request is used, shows the selection page.
    When a post request is used, assumes that it is a form submission
        from the selection page, parses the response, and then sends user
        to the next step in the flow
    """
33
    @method_decorator(login_required)
34
    def get(self, request, course_id, error=None):
35
        """ Displays the course mode choice page """
36

37 38
        course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)

39
        enrollment_mode, is_active = CourseEnrollment.enrollment_mode_for_user(request.user, course_key)
Julia Hansbrough committed
40
        upgrade = request.GET.get('upgrade', False)
Julia Hansbrough committed
41
        request.session['attempting_upgrade'] = upgrade
Julia Hansbrough committed
42

43
        # Inactive users always need to re-register
Julia Hansbrough committed
44 45
        # verified users do not need to register or upgrade
        # registered users who are not trying to upgrade do not need to re-register
46
        if is_active and (upgrade is False or enrollment_mode == 'verified'):
Julia Hansbrough committed
47
            return redirect(reverse('dashboard'))
48

49
        modes = CourseMode.modes_for_course_dict(course_key)
50
        donation_for_course = request.session.get("donation_for_course", {})
51
        chosen_price = donation_for_course.get(course_key, None)
52

53
        course = modulestore().get_course(course_key)
54
        context = {
55
            "course_modes_choose_url": reverse("course_modes_choose", kwargs={'course_id': course_key.to_deprecated_string()}),
56
            "modes": modes,
57
            "course_name": course.display_name_with_default,
58 59
            "course_org": course.display_org_with_default,
            "course_num": course.display_number_with_default,
60
            "chosen_price": chosen_price,
61
            "error": error,
62
            "upgrade": upgrade,
63
            "can_audit": "audit" in modes,
64
        }
65
        if "verified" in modes:
66 67 68 69 70
            context["suggested_prices"] = [
                decimal.Decimal(x.strip())
                for x in modes["verified"].suggested_prices.split(",")
                if x.strip()
            ]
71
            context["currency"] = modes["verified"].currency.upper()
72
            context["min_price"] = modes["verified"].min_price
73
            context["verified_name"] = modes["verified"].name
74
            context["verified_description"] = modes["verified"].description
75

76 77
        return render_to_response("course_modes/choose.html", context)

78
    @method_decorator(login_required)
79
    def post(self, request, course_id):
80
        """ Takes the form submission from the page and parses it """
81
        course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
82 83
        user = request.user

Sarina Canelake committed
84
        # This is a bit redundant with logic in student.views.change_enrollment,
85
        # but I don't really have the time to refactor it more nicely and test.
86
        course = modulestore().get_course(course_key)
87
        if not has_access(user, 'enroll', course):
88
            error_msg = _("Enrollment is closed")
89
            return self.get(request, course_id, error=error_msg)
90

91 92
        upgrade = request.GET.get('upgrade', False)

93
        requested_mode = self.get_requested_mode(request.POST)
94

95
        allowed_modes = CourseMode.modes_for_course_dict(course_key)
96 97 98 99
        if requested_mode not in allowed_modes:
            return HttpResponseBadRequest(_("Enrollment mode not supported"))

        if requested_mode in ("audit", "honor"):
100
            CourseEnrollment.enroll(user, course_key, requested_mode)
101 102
            return redirect('dashboard')

103 104
        mode_info = allowed_modes[requested_mode]

105
        if requested_mode == "verified":
106
            amount = request.POST.get("contribution") or \
107
                request.POST.get("contribution-other-amt") or 0
108

109 110 111 112 113
            try:
                # validate the amount passed in and force it into two digits
                amount_value = decimal.Decimal(amount).quantize(decimal.Decimal('.01'), rounding=decimal.ROUND_DOWN)
            except decimal.InvalidOperation:
                error_msg = _("Invalid amount selected.")
114
                return self.get(request, course_id, error=error_msg)
115

116
            # Check for minimum pricing
117
            if amount_value < mode_info.min_price:
118
                error_msg = _("No selected price or selected price is too low.")
119
                return self.get(request, course_id, error=error_msg)
120

121
            donation_for_course = request.session.get("donation_for_course", {})
122
            donation_for_course[course_key] = amount_value
123
            request.session["donation_for_course"] = donation_for_course
124 125
            if SoftwareSecurePhotoVerification.user_has_valid_or_pending(request.user):
                return redirect(
126
                    reverse('verify_student_verified',
127
                            kwargs={'course_id': course_key.to_deprecated_string()}) + "?upgrade={}".format(upgrade)
128
                )
129

130
            return redirect(
131
                reverse('verify_student_show_requirements',
132
                        kwargs={'course_id': course_key.to_deprecated_string()}) + "?upgrade={}".format(upgrade))
133

134
    def get_requested_mode(self, request_dict):
135
        """
136
        Given the request object of `user_choice`, return the
137 138
        corresponding course mode slug
        """
139 140 141 142 143 144
        if 'audit_mode' in request_dict:
            return 'audit'
        if 'certificate_mode' and request_dict.get("honor-code"):
            return 'honor'
        if 'certificate_mode' in request_dict:
            return 'verified'