Files
edx-platform/lms/djangoapps/verify_student/views.py

220 lines
8.2 KiB
Python

"""
"""
import json
import logging
import decimal
from mitxmako.shortcuts import render_to_response
from django.conf import settings
from django.core.urlresolvers import reverse
from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseRedirect
from django.shortcuts import redirect
from django.views.generic.base import View
from django.utils.decorators import method_decorator
from django.utils.translation import ugettext as _
from django.utils.http import urlencode
from django.contrib.auth.decorators import login_required
from course_modes.models import CourseMode
from student.models import CourseEnrollment
from student.views import course_from_id
from shoppingcart.models import Order, CertificateItem
from shoppingcart.processors.CyberSource import (
get_signed_purchase_params, get_purchase_endpoint
)
from verify_student.models import SoftwareSecurePhotoVerification
log = logging.getLogger(__name__)
class VerifyView(View):
@method_decorator(login_required)
def get(self, request, course_id):
"""
"""
# If the user has already been verified within the given time period,
# redirect straight to the payment -- no need to verify again.
if SoftwareSecurePhotoVerification.user_has_valid_or_pending(request.user):
return redirect(
reverse('verify_student_verified',
kwargs={'course_id': course_id}))
else:
# If they haven't completed a verification attempt, we have to
# restart with a new one. We can't reuse an older one because we
# won't be able to show them their encrypted photo_id -- it's easier
# bookkeeping-wise just to start over.
progress_state = "start"
verify_mode = CourseMode.mode_for_course(course_id, "verified")
if course_id in request.session.get("donation_for_course", {}):
chosen_price = request.session["donation_for_course"][course_id]
else:
chosen_price = verify_mode.min_price.format("{:g}")
context = {
"progress_state": progress_state,
"user_full_name": request.user.profile.name,
"course_id": course_id,
"course_name": course_from_id(course_id).display_name,
"purchase_endpoint": get_purchase_endpoint(),
"suggested_prices": [
decimal.Decimal(price)
for price in verify_mode.suggested_prices.split(",")
],
"currency": verify_mode.currency.upper(),
"chosen_price": chosen_price,
}
return render_to_response('verify_student/photo_verification.html', context)
class VerifiedView(View):
"""
View that gets shown once the user has already gone through the
verification flow
"""
@method_decorator(login_required)
def get(self, request, course_id):
"""
Handle the case where we have a get request
"""
verify_mode = CourseMode.mode_for_course(course_id, "verified")
if course_id in request.session.get("donation_for_course", {}):
chosen_price = request.session["donation_for_course"][course_id]
else:
chosen_price = verify_mode.min_price.format("{:g}")
context = {
"course_id": course_id,
"course_name": course_from_id(course_id).display_name,
"purchase_endpoint": get_purchase_endpoint(),
"currency": verify_mode.currency.upper(),
"chosen_price": chosen_price,
}
return render_to_response('verify_student/verified.html', context)
@login_required
def create_order(request):
"""
Submit PhotoVerification and create a new Order for this verified cert
"""
attempt = SoftwareSecurePhotoVerification(user=request.user)
attempt.status = "ready"
attempt.save()
course_id = request.POST['course_id']
donation_for_course = request.session.get('donation_for_course', {})
current_donation = donation_for_course.get(course_id, decimal.Decimal(0))
contribution = request.POST.get("contribution", donation_for_course.get(course_id, 0))
try:
amount = decimal.Decimal(contribution).quantize(decimal.Decimal('.01'), rounding=decimal.ROUND_DOWN)
except decimal.InvalidOperation:
return HttpResponseBadRequest(_("Selected price is not valid number."))
if amount != current_donation:
donation_for_course[course_id] = amount
request.session['donation_for_course'] = donation_for_course
verified_mode = CourseMode.modes_for_course_dict(course_id).get('verified', None)
# make sure this course has a verified mode
if not verified_mode:
return HttpResponseBadRequest(_("This course doesn't support verified certificates"))
if amount < verified_mode.min_price:
return HttpResponseBadRequest(_("No selected price or selected price is below minimum."))
# I know, we should check this is valid. All kinds of stuff missing here
cart = Order.get_cart_for_user(request.user)
cart.clear()
CertificateItem.add_to_order(cart, course_id, amount, 'verified')
params = get_signed_purchase_params(cart)
return HttpResponse(json.dumps(params), content_type="text/json")
@login_required
def show_requirements(request, course_id):
"""
Show the requirements necessary for
"""
context = { "course_id": course_id, "is_not_active": not request.user.is_active}
return render_to_response("verify_student/show_requirements.html", context)
def face_upload(request):
context = { "course_id": "edX/Certs101/2013_Test" }
return render_to_response("verify_student/face_upload.html", context)
def photo_id_upload(request):
context = { "course_id": "edX/Certs101/2013_Test" }
return render_to_response("verify_student/photo_id_upload.html", context)
def final_verification(request):
context = { "course_id": "edX/Certs101/2013_Test" }
return render_to_response("verify_student/final_verification.html", context)
def show_verification_page(request):
pass
def enroll(user, course_id, mode_slug):
"""
Enroll the user in a course for a certain mode.
This is the view you send folks to when they click on the enroll button.
This does NOT cover changing enrollment modes -- it's intended for new
enrollments only, and will just redirect to the dashboard if it detects
that an enrollment already exists.
"""
# If the user is already enrolled, jump to the dashboard. Yeah, we could
# do upgrades here, but this method is complicated enough.
if CourseEnrollment.is_enrolled(user, course_id):
return HttpResponseRedirect(reverse('dashboard'))
available_modes = CourseModes.modes_for_course(course_id)
# If they haven't chosen a mode...
if not mode_slug:
# Does this course support multiple modes of Enrollment? If so, redirect
# to a page that lets them choose which mode they want.
if len(available_modes) > 1:
return HttpResponseRedirect(
reverse('choose_enroll_mode', kwargs={'course_id': course_id})
)
# Otherwise, we use the only mode that's supported...
else:
mode_slug = available_modes[0].slug
# If the mode is one of the simple, non-payment ones, do the enrollment and
# send them to their dashboard.
if mode_slug in ("honor", "audit"):
CourseEnrollment.enroll(user, course_id, mode=mode_slug)
return HttpResponseRedirect(reverse('dashboard'))
if mode_slug == "verify":
if SoftwareSecurePhotoVerification.has_submitted_recent_request(user):
# Capture payment info
# Create an order
# Create a VerifiedCertificate order item
return HttpResponse.Redirect(reverse('verified'))
# There's always at least one mode available (default is "honor"). If they
# haven't specified a mode, we just assume it's
if not mode:
mode = available_modes[0]
elif len(available_modes) == 1:
if mode != available_modes[0]:
raise Exception()
mode = available_modes[0]
if mode == "honor":
CourseEnrollment.enroll(user, course_id)
return HttpResponseRedirect(reverse('dashboard'))