def test_get_run_data(self): """Test for the get_run_data method""" edx_user_data = CachedEdxUserData(self.user) run_data = edx_user_data.get_run_data(self.p1_course_run_keys[0]) assert isinstance(run_data, UserCachedRunData) assert isinstance(run_data.enrollment, Enrollment) assert isinstance(run_data.certificate, Certificate) assert isinstance(run_data.current_grade, CurrentGrade) assert run_data.enrollment.course_id == self.p1_course_run_keys[0] assert run_data.certificate.course_id == self.p1_course_run_keys[0] assert run_data.current_grade.course_id == self.p1_course_run_keys[0]
def test_edx_data_with_program(self): """Test that a user's edX data is filtered by program when specified""" p1_course_run_program = self.p1_course_run.course.program edx_user_data = CachedEdxUserData(self.user, program=p1_course_run_program) self.assert_edx_data_has_given_ids(edx_user_data, self.p1_course_run_keys) p2_course_run_program = self.p2_course_run_1.course.program edx_user_data = CachedEdxUserData(self.user, program=p2_course_run_program) self.assert_edx_data_has_given_ids(edx_user_data, self.p2_course_run_keys)
def has_object_permission(self, request, view, obj): """ Returns True if the user has permission to send a message to a course team. Args: request (Request): DRF request object view (View): DRF view object obj (Course): Course object Returns: boolean """ user = request.user program = obj.program # Make sure the user has an enrollment in the course's program if not ProgramEnrollment.objects.filter(user=user, program=program).exists(): return False # Make sure the user has paid for any course run for the given course edx_user_data = CachedEdxUserData(user) mmtrack = MMTrack(user, program, edx_user_data) course_run_keys = obj.courserun_set.values_list('edx_course_key', flat=True) return any([ mmtrack.has_paid(course_run_key) for course_run_key in course_run_keys ])
def setUpTestData(cls): cls.user = SocialUserFactory.create() cls.run_fa = CourseRunFactory.create( freeze_grade_date=now_in_utc() - timedelta(days=1), course__program__financial_aid_availability=True, ) cls.run_fa_with_cert = CourseRunFactory.create( freeze_grade_date=None, course__program=cls.run_fa.course.program, ) cls.run_no_fa = CourseRunFactory.create( freeze_grade_date=now_in_utc() + timedelta(days=1), course__program__financial_aid_availability=False, ) cls.run_no_fa_with_cert = CourseRunFactory.create( course__program=cls.run_no_fa.course.program, ) all_course_runs = ( cls.run_fa, cls.run_fa_with_cert, cls.run_no_fa, cls.run_no_fa_with_cert, ) for run in all_course_runs: if run.course.program.financial_aid_availability: FinancialAidFactory.create( user=cls.user, tier_program=TierProgramFactory.create( program=run.course.program, income_threshold=0, current=True), status=FinancialAidStatus.RESET, ) cls.enrollments = { course_run.edx_course_key: CachedEnrollmentFactory.create(user=cls.user, course_run=course_run) for course_run in all_course_runs } cls.current_grades = { course_run.edx_course_key: CachedCurrentGradeFactory.create(user=cls.user, course_run=course_run) for course_run in all_course_runs } cls.certificates = { course_run.edx_course_key: CachedCertificateFactory.create(user=cls.user, course_run=course_run) for course_run in (cls.run_fa_with_cert, cls.run_no_fa_with_cert) } cls.user_edx_data = CachedEdxUserData(cls.user)
def test_edx_data_fetch_and_set(self): """Test that a user's edX data is properly fetched and set onto object properties""" edx_user_data = CachedEdxUserData(self.user) assert isinstance(edx_user_data.enrollments, Enrollments) assert isinstance(edx_user_data.certificates, Certificates) assert isinstance(edx_user_data.current_grades, CurrentGrades) self.assert_edx_data_has_given_ids( edx_user_data, self.p1_course_run_keys + self.p2_course_run_keys)
def test_compute_grade_odd_grade(self, odd_value): """ Tests in case the grade coming from edX is not a number """ # test for grade computed on current grades test_values = ( (self.run_fa, api._compute_grade_for_fa, ), (self.run_no_fa, api._compute_grade_for_non_fa, ), ) for course_run, grade_func in test_values: course_key = course_run.edx_course_key current_grade = self.current_grades[course_key] current_grade.data['percent'] = odd_value current_grade.save() user_edx_data = CachedEdxUserData(self.user) run_data = user_edx_data.get_run_data(course_key) grade = grade_func(run_data) assert grade.grade == 0.0
def get_final_grade(user, course_run): """ Public function to compute final grades for the a user in a course run. Args: user (User): a django User course_run (CourseRun): a course run model object Returns: UserFinalGrade: a namedtuple of (grade, passed,) representing the final grade of the user in the course run and whether she passed it """ # pull the cached data for the user user_data = CachedEdxUserData(user, course_run.course.program) run_data = user_data.get_run_data(course_run.edx_course_key) # pick the right function final_grade_func = _get_compute_func(course_run) return final_grade_func(run_data)
def get_mmtrack(user, program): """ Creates mmtrack object for given user. Args: user (User): a Django user. program (programs.models.Program): program where the user is enrolled. Returns: mmtrack (dashboard.utils.MMTrack): a instance of all user information about a program """ edx_user_data = CachedEdxUserData(user, program=program) return MMTrack(user, program, edx_user_data)
def test_compute_grade_for_non_fa_certs(self, certificate_type, status, grade_result, payed_edx_result): """ Tests for _compute_grade_for_non_fa function with certificates of different status """ course_key = self.run_no_fa_with_cert.edx_course_key certificate = self.certificates[course_key] certificate.data.update(certificate_type=certificate_type, status=status) certificate.save() run_data = CachedEdxUserData(self.user).get_run_data(course_key) grade = api._compute_grade_for_non_fa(run_data) assert grade.passed is grade_result assert grade.grade == self.current_grades[course_key].data.get('percent') assert grade.payed_on_edx is payed_edx_result
def test_compute_grade_for_non_fa_enrollment_not_verified(self): """ Tests for _compute_grade_for_non_fa function in case there is no certificate and the enrollment is not verified """ course_key = self.run_no_fa.edx_course_key enrollment = self.enrollments.get(course_key) enrollment.data['mode'] = 'audit' enrollment.save() run3_data = CachedEdxUserData(self.user).get_run_data(course_key) grade3_from_cur_grade = api._compute_grade_for_non_fa(run3_data) assert grade3_from_cur_grade.passed is False assert grade3_from_cur_grade.grade == self.current_grades.get( self.run_no_fa.edx_course_key).data.get('percent') assert grade3_from_cur_grade.payed_on_edx is False
def is_coupon_redeemable(coupon, user): """ Returns true if the coupon is redeemable for the user, for any relevant course run. Args: coupon (Coupon): A coupon user (django.contrib.auth.models.User): A user Returns: bool: True if the coupon is redeemable by the user for some course run """ if not Program.objects.filter( programenrollment__user=user, programenrollment__program__course__courserun__edx_course_key__in= coupon.course_keys, live=True, ).exists(): return False if (not coupon.is_valid or # coupon must be enabled and within valid date range not coupon.user_has_redemptions_left( user) # coupon must not be used up ): return False if coupon.coupon_type == Coupon.DISCOUNTED_PREVIOUS_COURSE: # We validate in clean() that content_object is a Course if coupon_type is DISCOUNTED_PREVIOUS_RUN course = coupon.content_object program = course.program edx_user_data = CachedEdxUserData(user, program=program) mmtrack = MMTrack( user, program, edx_user_data, ) # For this coupon type the user must have already purchased a course run on edX return any((mmtrack.has_verified_enrollment(run.edx_course_key) for run in course.courserun_set.all())) return True
def has_object_permission(self, request, view, obj): """ Returns True if the user has the permission to message a specific learner. Args: request (Request): DRF request object view (View): DRF view object obj (Profile): Recipient Profile object Returns: boolean """ if not obj.email_optin: return False sender_user = request.user recipient_enrolled_program_ids = obj.user.programenrollment_set.values_list( 'program', flat=True) # If the sender is a staff/instructor in any of the recipients enrolled programs, the # sender has permission if sender_user.role_set.filter( role__in=[Staff.ROLE_ID, Instructor.ROLE_ID], program__id__in=recipient_enrolled_program_ids).exists(): return True # If the sender has paid for any course run in any of the recipient's enrolled programs, the # sender has permission matching_program_enrollments = ( sender_user.programenrollment_set.filter( program__id__in=recipient_enrolled_program_ids).select_related( 'program').all()) edx_user_data = CachedEdxUserData(sender_user) for program_enrollment in matching_program_enrollments: mmtrack = MMTrack(sender_user, program_enrollment.program, edx_user_data) if mmtrack.has_paid_for_any_in_program(): return True return False
def setUpTestData(cls): with mute_signals(post_save): cls.profile = profile = ProfileFactory.create() cls.user = profile.user EducationFactory.create(profile=profile) EmploymentFactory.create(profile=profile) # create a normal program program = ProgramFactory.create() cls.enrollments = cls._generate_cached_enrollments(cls.user, program, num_course_runs=2) certificate_grades_vals = [0.7, 0.8] cls.current_grades_vals = [0.9, 1.0] cls.certificates = [] cls.current_grades = [] for i, enrollment in enumerate(cls.enrollments): cls.certificates.append( CachedCertificateFactory.create( user=cls.user, course_run=enrollment.course_run, data={ "grade": certificate_grades_vals[i], "certificate_type": "verified", "course_id": enrollment.course_run.edx_course_key, "status": "downloadable", })) cls.current_grades.append( CachedCurrentGradeFactory.create( user=cls.user, course_run=enrollment.course_run, data={ "passed": True, "percent": cls.current_grades_vals[i], "course_key": enrollment.course_run.edx_course_key, })) FinalGradeFactory.create( user=cls.user, course_run=enrollment.course_run, grade=certificate_grades_vals[i], passed=True, ) non_fa_cached_edx_data = CachedEdxUserData(cls.user, program=program) non_fa_mmtrack = MMTrack(cls.user, program, non_fa_cached_edx_data) cls.serialized_enrollments = UserProgramSearchSerializer.serialize_enrollments( non_fa_mmtrack) cls.serialized_course_enrollments = UserProgramSearchSerializer.serialize_course_enrollments( non_fa_mmtrack) cls.semester_enrollments = UserProgramSearchSerializer.serialize_course_runs_enrolled( non_fa_mmtrack) cls.program_enrollment = ProgramEnrollment.objects.create( user=cls.user, program=program) # create a financial aid program cls.fa_program, _ = create_program() cls.fa_program_enrollment = ProgramEnrollment.objects.create( user=cls.user, program=cls.fa_program) cls.fa_enrollments = cls._generate_cached_enrollments( cls.user, cls.fa_program, num_course_runs=2) cls.current_grades = [] for i, enrollment in enumerate(cls.fa_enrollments): order = OrderFactory.create(user=cls.user, status='fulfilled') LineFactory.create(order=order, course_key=enrollment.course_run.edx_course_key) cls.current_grades.append( CachedCurrentGradeFactory.create( user=cls.user, course_run=enrollment.course_run, data={ "passed": True, "percent": cls.current_grades_vals[i], "course_key": enrollment.course_run.edx_course_key, })) FinalGradeFactory.create( user=cls.user, course_run=enrollment.course_run, grade=cls.current_grades_vals[i], passed=True, ) fa_cached_edx_data = CachedEdxUserData(cls.user, program=cls.fa_program) fa_mmtrack = MMTrack(cls.user, cls.fa_program, fa_cached_edx_data) cls.fa_serialized_course_enrollments = ( UserProgramSearchSerializer.serialize_course_enrollments( fa_mmtrack)) cls.fa_serialized_enrollments = ( UserProgramSearchSerializer.serialize_enrollments(fa_mmtrack))