125 lines
4.5 KiB
Python
125 lines
4.5 KiB
Python
"""
|
|
Views for support dashboard
|
|
"""
|
|
import logging
|
|
|
|
from django.contrib.auth.models import User
|
|
from django.views.generic.edit import FormView
|
|
from django.views.generic.base import TemplateView
|
|
from django.utils.translation import ugettext as _
|
|
from django.http import HttpResponseRedirect
|
|
from django.contrib import messages
|
|
from django import forms
|
|
from student.models import CourseEnrollment
|
|
from opaque_keys.edx.keys import CourseKey
|
|
from opaque_keys import InvalidKeyError
|
|
from opaque_keys.edx.locations import SlashSeparatedCourseKey
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
class RefundForm(forms.Form): # pylint: disable=incomplete-protocol
|
|
"""
|
|
Form for manual refunds
|
|
"""
|
|
user = forms.EmailField(label=_("Email Address"), required=True)
|
|
course_id = forms.CharField(label=_("Course ID"), required=True)
|
|
confirmed = forms.CharField(widget=forms.HiddenInput, required=False)
|
|
|
|
def clean_user(self):
|
|
"""
|
|
validate user field
|
|
"""
|
|
user_email = self.cleaned_data['user']
|
|
try:
|
|
user = User.objects.get(email=user_email)
|
|
except User.DoesNotExist:
|
|
raise forms.ValidationError(_("User not found"))
|
|
return user
|
|
|
|
def clean_course_id(self):
|
|
"""
|
|
validate course id field
|
|
"""
|
|
course_id = self.cleaned_data['course_id']
|
|
try:
|
|
course_key = CourseKey.from_string(course_id)
|
|
except InvalidKeyError:
|
|
try:
|
|
course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
|
|
except InvalidKeyError:
|
|
raise forms.ValidationError(_("Invalid course id"))
|
|
return course_key
|
|
|
|
def clean(self):
|
|
"""
|
|
clean form
|
|
"""
|
|
user, course_id = self.cleaned_data.get('user'), self.cleaned_data.get('course_id')
|
|
if user and course_id:
|
|
self.cleaned_data['enrollment'] = enrollment = CourseEnrollment.get_or_create_enrollment(user, course_id)
|
|
if enrollment.refundable():
|
|
raise forms.ValidationError(_("Course {course_id} not past the refund window.").format(course_id=course_id))
|
|
try:
|
|
self.cleaned_data['cert'] = enrollment.certificateitem_set.filter(mode='verified', status='purchased')[0]
|
|
except IndexError:
|
|
raise forms.ValidationError(_("No order found for {user} in course {course_id}").format(user=user, course_id=course_id))
|
|
return self.cleaned_data
|
|
|
|
def is_valid(self):
|
|
"""
|
|
returns whether form is valid
|
|
"""
|
|
is_valid = super(RefundForm, self).is_valid()
|
|
if is_valid and self.cleaned_data.get('confirmed') != 'true':
|
|
# this is a two-step form: first look up the data, then issue the refund.
|
|
# first time through, set the hidden "confirmed" field to true and then redisplay the form
|
|
# second time through, do the unenrollment/refund.
|
|
data = dict(self.data.items())
|
|
self.cleaned_data['confirmed'] = data['confirmed'] = 'true'
|
|
self.data = data
|
|
is_valid = False
|
|
return is_valid
|
|
|
|
|
|
class SupportDash(TemplateView):
|
|
"""
|
|
Support dashboard view
|
|
"""
|
|
template_name = 'dashboard/support.html'
|
|
|
|
|
|
class Refund(FormView):
|
|
"""
|
|
Refund form view
|
|
"""
|
|
template_name = 'dashboard/_dashboard_refund.html'
|
|
form_class = RefundForm
|
|
success_url = '/support/'
|
|
|
|
def get_context_data(self, **kwargs):
|
|
"""
|
|
extra context data to add to page
|
|
"""
|
|
form = getattr(kwargs['form'], 'cleaned_data', {})
|
|
if form.get('confirmed') == 'true':
|
|
kwargs['cert'] = form.get('cert')
|
|
kwargs['enrollment'] = form.get('enrollment')
|
|
return kwargs
|
|
|
|
def form_valid(self, form):
|
|
"""
|
|
unenrolls student, issues refund
|
|
"""
|
|
user = form.cleaned_data['user']
|
|
course_id = form.cleaned_data['course_id']
|
|
enrollment = form.cleaned_data['enrollment']
|
|
cert = form.cleaned_data['cert']
|
|
enrollment.can_refund = True
|
|
enrollment.update_enrollment(is_active=False)
|
|
|
|
log.info(u"%s manually refunded %s %s", self.request.user, user, course_id)
|
|
messages.success(self.request, _("Unenrolled {user} from {course_id}").format(user=user, course_id=course_id))
|
|
messages.success(self.request, _("Refunded {cost} for order id {order_id}").format(cost=cert.unit_cost, order_id=cert.order.id))
|
|
return HttpResponseRedirect('/support/refund/')
|