def test_course_run_missing_overview_not_fulfillable(self): entitlement = CourseEntitlementFactory.create(mode=CourseMode.VERIFIED) assert not is_course_run_entitlement_fulfillable( CourseKey.from_string('course-v1:edx+FakeCourse+3T2017'), entitlement )
def get_fulfillable_entitlement_for_user_course_run( cls, user, course_run_key): """ Retrieves a fulfillable entitlement for the user and the given course run. Arguments: user (User): The user that we are inspecting the entitlements for. course_run_key (CourseKey): The course run Key. Returns: CourseEntitlement: The most recent fulfillable CourseEntitlement, None otherwise. """ # Check if the User has any fulfillable entitlements. # Note: Wait to retrieve the Course UUID until we have confirmed the User has fulfillable entitlements. # This was done to avoid calling the APIs when the User does not have an entitlement. entitlements = cls.get_fulfillable_entitlements(user) if entitlements: course_uuid = get_course_uuid_for_course(course_run_key) if course_uuid: entitlement = entitlements.filter( course_uuid=course_uuid).first() if (entitlement and is_course_run_entitlement_fulfillable( course_run_key=course_run_key, entitlement=entitlement) and entitlement.is_entitlement_redeemable()): return entitlement return None
def get_upgradeable_enrollments_for_entitlement(self, entitlement): """ Retrieve all the CourseEnrollments that are upgradeable for a given CourseEntitlement Arguments: entitlement: CourseEntitlement that we are requesting the CourseEnrollments for. Returns: list: List of upgradeable CourseEnrollments """ # find all course_runs within the course course_runs = get_course_runs_for_course(entitlement.course_uuid) # check if the user has enrollments for any of the course_runs upgradeable_enrollments = [] for course_run in course_runs: course_run_id = CourseKey.from_string(course_run.get('key')) enrollment = CourseEnrollment.get_enrollment( entitlement.user, course_run_id) if (enrollment and enrollment.is_active and is_course_run_entitlement_fulfillable( course_run_id, entitlement)): upgradeable_enrollments.append(enrollment) return upgradeable_enrollments
def test_course_run_not_fulfillable_enrollment_start_in_future(self): course_overview = self.create_course(start_from_now=-3, end_from_now=2, enrollment_start_from_now=2, enrollment_end_from_now=4) entitlement = CourseEntitlementFactory.create(mode=CourseMode.VERIFIED) assert not is_course_run_entitlement_fulfillable( course_overview.id, entitlement)
def test_course_run_fulfillable_already_enrolled_course_ended(self): course_overview = self.create_course( start_from_now=-3, end_from_now=-1, enrollment_start_from_now=-2, enrollment_end_from_now=-1, ) entitlement = CourseEntitlementFactory.create(mode=CourseMode.VERIFIED) CourseEnrollmentFactory.create(user=entitlement.user, course_id=course_overview.id) assert is_course_run_entitlement_fulfillable(course_overview.id, entitlement)
def test_course_run_not_fulfillable_no_start_date(self): course_overview = self.create_course(start_from_now=-2, end_from_now=2, enrollment_start_from_now=-1, enrollment_end_from_now=1) course_overview.start = None course_overview.save() entitlement = CourseEntitlementFactory.create(mode=CourseMode.VERIFIED) assert not is_course_run_entitlement_fulfillable( course_overview.id, entitlement)
def test_course_run_fulfillable_user_enrolled(self): course_overview = self.create_course( start_from_now=-3, end_from_now=2, enrollment_start_from_now=-2, enrollment_end_from_now=1 ) entitlement = CourseEntitlementFactory.create(mode=CourseMode.VERIFIED) # Enroll User in the Course, but do not update the entitlement CourseEnrollmentFactory.create(user=entitlement.user, course_id=course_overview.id) assert is_course_run_entitlement_fulfillable(course_overview.id, entitlement)
def get_fulfillable_course_runs_for_entitlement(entitlement, course_runs): """ Looks through the list of course runs and returns the course runs that can be applied to the entitlement. Args: entitlement (CourseEntitlement): The CourseEntitlement to which a course run is to be applied. course_runs (list): List of course run that we would like to apply to the entitlement. Return: list: A list of sessions that a user can apply to the provided entitlement. """ enrollable_sessions = [] # Only retrieve list of published course runs that can still be enrolled and upgraded search_time = datetime.datetime.now(UTC) for course_run in course_runs: course_id = CourseKey.from_string(course_run.get('key')) (user_enrollment_mode, is_active) = CourseEnrollment.enrollment_mode_for_user( user=entitlement.user, course_id=course_id) is_enrolled_in_mode = is_active and (user_enrollment_mode == entitlement.mode) if (is_enrolled_in_mode and entitlement.enrollment_course_run and course_id == entitlement.enrollment_course_run.course_id): # User is enrolled in the course so we should include it in the list of enrollable sessions always # this will ensure it is available for the UI enrollable_sessions.append(course_run) elif not is_enrolled_in_mode and is_course_run_entitlement_fulfillable( course_id, entitlement, search_time): enrollable_sessions.append(course_run) enrollable_sessions.sort(key=lambda session: session.get('start')) return enrollable_sessions
def create(self, request, uuid): """ On POST this method will be called and will handle enrolling a user in the provided course_run_id from the data. This is called on a specific entitlement UUID so the course_run_id has to correspond to the Course that is assigned to the Entitlement. When this API is called for a user who is already enrolled in a run that User will be unenrolled from their current run and enrolled in the new run if it is available. """ course_run_id = request.data.get('course_run_id', None) if not course_run_id: return Response(status=status.HTTP_400_BAD_REQUEST, data='The Course Run ID was not provided.') # Verify that the user has an Entitlement for the provided Entitlement UUID. try: entitlement = CourseEntitlement.objects.get(uuid=uuid, user=request.user, expired_at=None) except CourseEntitlement.DoesNotExist: return Response( status=status.HTTP_400_BAD_REQUEST, data= 'The Entitlement for this UUID does not exist or is Expired.') # Verify the course run ID is of the same Course as the Course entitlement. course_run_valid = self._verify_course_run_for_entitlement( entitlement, course_run_id) if not course_run_valid: return Response( status=status.HTTP_400_BAD_REQUEST, data={ 'message': 'The Course Run ID is not a match for this Course Entitlement.' }) try: course_run_key = CourseKey.from_string(course_run_id) except InvalidKeyError: return Response( status=status.HTTP_400_BAD_REQUEST, data={ 'message': 'Invalid {course_id}'.format(course_id=course_run_id) }) # Verify that the run is fullfillable if not is_course_run_entitlement_fulfillable(course_run_key, entitlement): return Response( status=status.HTTP_400_BAD_REQUEST, data={ 'message': 'The User is unable to enroll in Course Run {course_id}, it is not available.' .format(course_id=course_run_id) }) # Determine if this is a Switch session or a simple enroll and handle both. if entitlement.enrollment_course_run is None: response = self._enroll_entitlement(entitlement=entitlement, course_run_key=course_run_key, user=request.user) if response: return response elif entitlement.enrollment_course_run.course_id != course_run_id: _unenroll_entitlement( course_entitlement=entitlement, course_run_key=entitlement.enrollment_course_run.course_id) response = self._enroll_entitlement(entitlement=entitlement, course_run_key=course_run_key, user=request.user) if response: return response return Response(status=status.HTTP_201_CREATED, data={ 'course_run_id': course_run_id, })