diff --git a/common/djangoapps/student/models.py b/common/djangoapps/student/models.py index 3958dfe48f23d23437c930339fdc880ae6d94e25..794c6ef7b9f203b4b44e422c48b5b17e6e82d586 100644 --- a/common/djangoapps/student/models.py +++ b/common/djangoapps/student/models.py @@ -26,6 +26,7 @@ from django.dispatch import receiver import django.dispatch from django.forms import ModelForm, forms +from course_modes.models import CourseMode import comment_client as cc from pytz import UTC @@ -926,6 +927,18 @@ class CourseEnrollment(models.Model): self.is_active = False self.save() + def refundable(self): + """ + For paid/verified certificates, students may receive a refund IFF they have + a verified certificate and the deadline for refunds has not yet passed. + """ + course_mode = CourseMode.mode_for_course(self.course_id, 'verified') + if course_mode is None: + return False + else: + return True + + class CourseEnrollmentAllowed(models.Model): """ diff --git a/common/djangoapps/student/tests/tests.py b/common/djangoapps/student/tests/tests.py index 315b6e928510cbe6007049cdaff1cff475c03ef2..41a95ff13ad0b420d1a7e9c75104496ea5ae0256 100644 --- a/common/djangoapps/student/tests/tests.py +++ b/common/djangoapps/student/tests/tests.py @@ -256,6 +256,22 @@ class DashboardTest(TestCase): self.assertFalse(course_mode_info['show_upsell']) self.assertIsNone(course_mode_info['days_for_upsell']) + def test_refundable(self): + verified_mode = CourseModeFactory.create( + course_id=self.course.id, + mode_slug='verified', + mode_display_name='Verified', + expiration_date=(datetime.now(pytz.UTC) + timedelta(days=1)).date() + ) + enrollment = CourseEnrollment.enroll(self.user, self.course.id, mode='verified') + + self.assertTrue(enrollment.refundable()) + + verified_mode.expiration_date = (datetime.now(pytz.UTC) - timedelta(days=1)).date() + verified_mode.save() + self.assertFalse(enrollment.refundable()) + + class EnrollInCourseTest(TestCase): """Tests enrolling and unenrolling in courses.""" diff --git a/common/djangoapps/student/views.py b/common/djangoapps/student/views.py index 00a06495a46380f5c0511687b64b27d9092f9eb8..a3195e11a4eb9a0ec81bbe1b2b507120e90d17d7 100644 --- a/common/djangoapps/student/views.py +++ b/common/djangoapps/student/views.py @@ -48,7 +48,6 @@ from student.forms import PasswordResetFormNoActive from verify_student.models import SoftwareSecurePhotoVerification from certificates.models import CertificateStatuses, certificate_status_for_student -from shoppingcart.models import CertificateItem from xmodule.course_module import CourseDescriptor from xmodule.modulestore.exceptions import ItemNotFoundError @@ -341,7 +340,7 @@ def dashboard(request): verification_status, verification_msg = SoftwareSecurePhotoVerification.user_status(user) show_refund_option_for = frozenset(course.id for course, _enrollment in courses - if (has_access(request.user, course, 'refund') and (_enrollment.mode == "verified"))) + if _enrollment.refundable()) # get info w.r.t ExternalAuthMap external_auth_map = None diff --git a/lms/djangoapps/courseware/access.py b/lms/djangoapps/courseware/access.py index 4535ff2616ad23faa7edbc4f2f43beec886959df..7836ab8bbce5d6f159b2c374b5ba8ded5f5c0fc7 100644 --- a/lms/djangoapps/courseware/access.py +++ b/lms/djangoapps/courseware/access.py @@ -14,7 +14,6 @@ from xmodule.modulestore import Location from xmodule.x_module import XModule, XModuleDescriptor from student.models import CourseEnrollmentAllowed -from course_modes.models import CourseMode from external_auth.models import ExternalAuthMap from courseware.masquerade import is_masquerading_as_student from django.utils.timezone import UTC @@ -203,24 +202,11 @@ def _has_access_course_desc(user, course, action): return can_enroll() or can_load() - def can_refund(): - """ - For paid/verified certificates, students may receive a refund IFF they have - a verified certificate and the deadline for refunds has not yet passed. - """ - course_mode = CourseMode.mode_for_course(course.id, 'verified') - if course_mode is None: - return False - else: - return True - - checkers = { 'load': can_load, 'load_forum': can_load_forum, 'enroll': can_enroll, 'see_exists': see_exists, - 'refund': can_refund, 'staff': lambda: _has_staff_access_to_descriptor(user, course), 'instructor': lambda: _has_instructor_access_to_descriptor(user, course), } diff --git a/lms/djangoapps/courseware/tests/test_access.py b/lms/djangoapps/courseware/tests/test_access.py index d05a753f44ddee642de16bde718b0abc69b56fca..bad5f95e0cca01589224f1e40c93b46a8e129cae 100644 --- a/lms/djangoapps/courseware/tests/test_access.py +++ b/lms/djangoapps/courseware/tests/test_access.py @@ -10,10 +10,6 @@ from .factories import CourseEnrollmentAllowedFactory import datetime import pytz -from student.tests.factories import UserFactory -from xmodule.modulestore.tests.factories import CourseFactory -from course_modes.tests.factories import CourseModeFactory - @override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class AccessTestCase(TestCase): @@ -116,28 +112,3 @@ class AccessTestCase(TestCase): # TODO: # Non-staff cannot enroll outside the open enrollment period if not specifically allowed - - def test__has_access_refund(self): - today = datetime.datetime.now(pytz.utc) - one_day_extra = datetime.timedelta(days=1) - user = UserFactory.create() - - course_nonrefundable_id = 'nonrefundable/test/Test_Course' - course_nonrefundable = CourseFactory.create(org='nonrefundable', number='test', run='course', display_name='Test Course') - course_mode_nonrefundable = CourseModeFactory.create(course_id=course_nonrefundable_id, - mode_slug='verified', - expiration_date=(today - one_day_extra)) - course_mode_nonrefundable.save() - - course_refundable_id = 'refundable/test/Test_Course' - course_refundable = CourseFactory.create(org='refundable', number='test', run='course', display_name='Test Course') - course_mode_refundable = CourseModeFactory.create(course_id=course_refundable_id, - mode_slug='verified', - expiration_date=(today + one_day_extra)) - course_mode_refundable.save() - - # User cannot receive a refund one day after the expiration date - self.assertFalse(access._has_access_course_desc(user, course_nonrefundable, 'refund')) - - # After two weeks, user may no longer receive a refund - self.assertTrue(access._has_access_course_desc(user, course_refundable, 'refund')) diff --git a/lms/templates/dashboard.html b/lms/templates/dashboard.html index 10cccbc075fe1fe2f6ff5e457e5f2ffb8ad71f65..2a24912633f1d61dd260b2a74dec5864e47528ae 100644 --- a/lms/templates/dashboard.html +++ b/lms/templates/dashboard.html @@ -191,7 +191,7 @@ <% show_email_settings = (course.id in show_email_settings_for) %> <% course_mode_info = all_course_modes.get(course.id) %> <% show_refund_option = (course.id in show_refund_option_for) %> - <%include file='dashboard/dashboard_course_listing.html' args="course=course, enrollment=enrollment, show_courseware_link=show_courseware_link, cert_status=cert_status, show_email_settings=show_email_settings, course_mode_info=course_mode_info, show_refund_option = show_refund_option" /> + <%include file='dashboard/_dashboard_course_listing.html' args="course=course, enrollment=enrollment, show_courseware_link=show_courseware_link, cert_status=cert_status, show_email_settings=show_email_settings, course_mode_info=course_mode_info, show_refund_option = show_refund_option" /> % endfor </ul>