diff --git a/lms/djangoapps/support/tests/test_refund.py b/lms/djangoapps/support/tests/test_refund.py
deleted file mode 100644
index df763cb3ea..0000000000
--- a/lms/djangoapps/support/tests/test_refund.py
+++ /dev/null
@@ -1,130 +0,0 @@
-"""
-Tests for refunds on the support dashboard
-
-DEPRECATION WARNING:
-This test suite is deliberately separate from the other view tests
-so we can easily deprecate it once the transition from shoppingcart
-to the E-Commerce service is complete.
-
-"""
-
-
-import datetime
-
-import pytz
-from django.test.client import Client
-from mock import patch
-
-from course_modes.models import CourseMode
-from shoppingcart.models import CertificateItem, Order
-from student.models import CourseEnrollment
-from student.roles import SupportStaffRole
-from student.tests.factories import UserFactory
-from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
-from xmodule.modulestore.tests.factories import CourseFactory
-
-
-class RefundTests(ModuleStoreTestCase):
- """
- Tests for the manual refund page
- """
-
- def setUp(self):
- super(RefundTests, self).setUp()
-
- self.course = CourseFactory.create(
- org='testorg', number='run1', display_name='refundable course'
- )
- self.course_id = self.course.location.course_key
- self.client = Client()
- self.admin = UserFactory.create(
- username='test_admin',
- email='test_admin+support@edx.org',
- password='foo'
- )
- SupportStaffRole().add_users(self.admin)
- self.client.login(username=self.admin.username, password='foo')
-
- self.student = UserFactory.create(
- username='student',
- email='student+refund@edx.org'
- )
- self.course_mode = CourseMode.objects.get_or_create(
- course_id=self.course_id,
- mode_slug='verified',
- min_price=1
- )[0]
-
- self.order = None
- self.form_pars = {'course_id': str(self.course_id), 'user': self.student.email}
-
- def tearDown(self):
- self.course_mode.delete()
- Order.objects.filter(user=self.student).delete()
- super(RefundTests, self).tearDown()
-
- def _enroll(self, purchase=True):
- CourseEnrollment.enroll(self.student, self.course_id, self.course_mode.mode_slug)
- if purchase:
- self.order = Order.get_cart_for_user(self.student)
- CertificateItem.add_to_order(self.order, self.course_id, 1, self.course_mode.mode_slug)
- self.order.purchase()
- self.course_mode.expiration_datetime = datetime.datetime(1983, 4, 6, tzinfo=pytz.UTC)
- self.course_mode.save()
-
- def test_support_access(self):
- response = self.client.get('/support/')
- self.assertTrue(response.status_code, 200)
- self.assertContains(response, 'Manual Refund')
- response = self.client.get('/support/refund/')
- self.assertTrue(response.status_code, 200)
-
- # users without the permission can't access support
- SupportStaffRole().remove_users(self.admin)
- response = self.client.get('/support/')
- self.assertTrue(response.status_code, 302)
-
- response = self.client.get('/support/refund/')
- self.assertTrue(response.status_code, 302)
-
- def test_bad_courseid(self):
- response = self.client.post('/support/refund/', {'course_id': 'foo', 'user': self.student.email})
- self.assertContains(response, 'Course id invalid')
-
- def test_bad_user(self):
- response = self.client.post('/support/refund/', {'course_id': str(self.course_id), 'user': 'unknown@foo.com'})
- self.assertContains(response, 'User not found')
-
- @patch('student.models.CourseEnrollment.refund_cutoff_date')
- def test_not_refundable(self, cutoff_date):
- self._enroll()
- self.course_mode.expiration_datetime = datetime.datetime(2033, 4, 6, tzinfo=pytz.UTC)
- self.course_mode.save()
- cutoff_date.return_value = datetime.datetime.now(pytz.UTC) + datetime.timedelta(days=1)
- response = self.client.post('/support/refund/', self.form_pars)
- self.assertContains(response, 'not past the refund window')
-
- def test_no_order(self):
- self._enroll(purchase=False)
- response = self.client.post('/support/refund/', self.form_pars)
- self.assertContains(response, u'No order found for %s' % self.student.username)
-
- def test_valid_order(self):
- self._enroll()
- response = self.client.post('/support/refund/', self.form_pars)
- self.assertContains(response, "About to refund this order")
- self.assertContains(response, "enrolled")
- self.assertContains(response, "CertificateItem Status")
-
- def test_do_refund(self):
- self._enroll()
- pars = self.form_pars
- pars['confirmed'] = 'true'
- response = self.client.post('/support/refund/', pars)
- self.assertTrue(response.status_code, 302)
- response = self.client.get(response.get('location'))
-
- self.assertContains(response, u"Unenrolled %s from" % self.student)
- self.assertContains(response, "Refunded 1.00 for order id")
-
- self.assertFalse(CourseEnrollment.is_enrolled(self.student, self.course_id))
diff --git a/lms/djangoapps/support/tests/test_views.py b/lms/djangoapps/support/tests/test_views.py
index a899bc572a..babfa2f94f 100644
--- a/lms/djangoapps/support/tests/test_views.py
+++ b/lms/djangoapps/support/tests/test_views.py
@@ -128,7 +128,6 @@ class SupportViewAccessTests(SupportViewTestCase):
in itertools.product((
'support:index',
'support:certificates',
- 'support:refund',
'support:enrollment',
'support:enrollment_list',
'support:manage_user',
@@ -156,7 +155,6 @@ class SupportViewAccessTests(SupportViewTestCase):
@ddt.data(
"support:index",
"support:certificates",
- "support:refund",
"support:enrollment",
"support:enrollment_list",
"support:manage_user",
@@ -185,7 +183,6 @@ class SupportViewIndexTests(SupportViewTestCase):
EXPECTED_URL_NAMES = [
"support:certificates",
- "support:refund",
"support:link_program_enrollments",
]
diff --git a/lms/djangoapps/support/urls.py b/lms/djangoapps/support/urls.py
index 6dcbe5a063..5ebd6a7bcb 100644
--- a/lms/djangoapps/support/urls.py
+++ b/lms/djangoapps/support/urls.py
@@ -13,7 +13,6 @@ from support.views.feature_based_enrollments import FeatureBasedEnrollmentsSuppo
from support.views.index import index
from support.views.manage_user import ManageUserDetailView, ManageUserSupportView
from support.views.program_enrollments import LinkProgramEnrollmentSupportView, ProgramEnrollmentsInspectorView
-from support.views.refund import RefundSupportView
COURSE_ENTITLEMENTS_VIEW = EntitlementSupportView.as_view()
@@ -21,7 +20,6 @@ app_name = 'support'
urlpatterns = [
url(r'^$', index, name="index"),
url(r'^certificates/?$', CertificatesSupportView.as_view(), name="certificates"),
- url(r'^refund/?$', RefundSupportView.as_view(), name="refund"),
url(r'^enrollment/?$', EnrollmentSupportView.as_view(), name="enrollment"),
url(r'^course_entitlement/?$', COURSE_ENTITLEMENTS_VIEW, name="course_entitlement"),
url(r'^contact_us/?$', ContactUsView.as_view(), name="contact_us"),
diff --git a/lms/djangoapps/support/views/index.py b/lms/djangoapps/support/views/index.py
index 409177ac6d..47d925d4e4 100644
--- a/lms/djangoapps/support/views/index.py
+++ b/lms/djangoapps/support/views/index.py
@@ -15,14 +15,6 @@ SUPPORT_INDEX_URLS = [
"name": _("Certificates"),
"description": _("View and regenerate certificates."),
},
-
- # DEPRECATION WARNING: We can remove this end-point
- # once shoppingcart has been replaced by the E-Commerce service.
- {
- "url": reverse_lazy("support:refund"),
- "name": _("Manual Refund"),
- "description": _("Track refunds issued directly through CyberSource."),
- },
{
"url": reverse_lazy("support:enrollment"),
"name": _("Enrollment"),
diff --git a/lms/djangoapps/support/views/refund.py b/lms/djangoapps/support/views/refund.py
deleted file mode 100644
index b7385414b9..0000000000
--- a/lms/djangoapps/support/views/refund.py
+++ /dev/null
@@ -1,142 +0,0 @@
-"""
-Views for manual refunds in the student support UI.
-
-This interface is used by the support team to track refunds
-entered manually in CyberSource (our payment gateway).
-
-DEPRECATION WARNING:
-We are currently in the process of replacing lms/djangoapps/shoppingcart
-with an E-Commerce service that supports automatic refunds. Once that
-transition is complete, we can remove this view.
-
-"""
-
-
-import logging
-
-from django import forms
-from django.contrib import messages
-from django.contrib.auth.models import User
-from django.http import HttpResponseRedirect
-from django.utils.decorators import method_decorator
-from django.utils.translation import ugettext as _
-from django.views.generic.edit import FormView
-
-from openedx.core.lib.courses import clean_course_id
-from student.models import CourseEnrollment
-from support.decorators import require_support_permission
-
-log = logging.getLogger(__name__)
-
-
-class RefundForm(forms.Form):
- """
- 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 the course id
- """
- return clean_course_id(self)
-
- 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():
- msg = _(u"Course {course_id} not past the refund window.").format(course_id=course_id)
- raise forms.ValidationError(msg)
- try:
- self.cleaned_data['cert'] = enrollment.certificateitem_set.filter(
- mode='verified',
- status='purchased'
- )[0]
- except IndexError:
- msg = _(u"No order found for {user} in course {course_id}").format(user=user, course_id=course_id)
- raise forms.ValidationError(msg)
- 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(list(self.data.items()))
- self.cleaned_data['confirmed'] = data['confirmed'] = 'true'
- self.data = data
- is_valid = False
- return is_valid
-
-
-class RefundSupportView(FormView):
- """
- Refund form view
- """
- template_name = 'support/refund.html'
- form_class = RefundForm
- success_url = '/support/'
-
- @method_decorator(require_support_permission)
- def dispatch(self, *args, **kwargs):
- return super(RefundSupportView, self).dispatch(*args, **kwargs)
-
- def get_context_data(self, **kwargs):
- """
- extra context data to add to page
- """
- kwargs = super(RefundSupportView, self).get_context_data(**kwargs)
- 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,
- _(u"Unenrolled {user} from {course_id}").format(
- user=user,
- course_id=course_id
- )
- )
- messages.success(
- self.request,
- _(u"Refunded {cost} for order id {order_id}").format(
- cost=cert.unit_cost,
- order_id=cert.order.id
- )
- )
- return HttpResponseRedirect('/support/refund/')
diff --git a/lms/templates/support/refund.html b/lms/templates/support/refund.html
deleted file mode 100644
index d45dd149f6..0000000000
--- a/lms/templates/support/refund.html
+++ /dev/null
@@ -1,83 +0,0 @@
-## mako
-
-<%page expression_filter="h"/>
-
-<%!
-from django.utils.translation import ugettext as _
-from django.utils.html import escape
-%>
-
-<%inherit file="../main.html"/>
-
-<%block name="title">
-
-Manual Refund
-
-%block>
-<%block name="headextra">
-
-
-%block>
-
-
-<%block name="body">
-
-
-
${_("Manual Refund")}
- % if messages:
-
- % for message in messages:
- - ${message}
- % endfor
-
- % endif
-
-
- % if cert:
-
-
- ${_("About to refund this order:")}
-
-
- ${_("Order Id:")} ${cert.order.id}
-
-
- ${_("Enrollment:")} ${escape(enrollment.course_id)} ${enrollment.mode}
- (${_("enrolled") if enrollment.is_active else _("unenrolled")})
-
-
- ${_("Cost:")} ${cert.unit_cost} ${cert.currency}
-
-
- ${_("CertificateItem Status:")} ${cert.status}
-
-
- ${_("Order Status:")} ${cert.order.status}
-
-
- ${_("Fulfilled Time:")} ${cert.fulfilled_time}
-
-
- ${_("Refund Request Time:")} ${cert.refund_requested_time}
-
-
- % endif
-
-
-%block>