Esempio n. 1
0
 def test_validate_certificate_settings_v2(self, stored_date,
                                           stored_behavior, expected_date,
                                           expected_behavior):
     assert CourseDetails.validate_certificate_settings(
         stored_date, stored_behavior) == (expected_date, expected_behavior)
Esempio n. 2
0
 def test_validate_certificate_settings_v1(self, stored_date,
                                           stored_behavior, expected_date,
                                           expected_behavior):
     """Test that method just returns passed in arguments if v2 is off"""
     assert CourseDetails.validate_certificate_settings(
         stored_date, stored_behavior) == (expected_date, expected_behavior)
Esempio n. 3
0
    def _create_or_update(cls, course):  # lint-amnesty, pylint: disable=too-many-statements
        """
        Creates or updates a CourseOverview object from a CourseBlock.

        Does not touch the database, simply constructs and returns an overview
        from the given course.

        Arguments:
            course (CourseBlock): any course descriptor object

        Returns:
            CourseOverview: created or updated overview extracted from the given course
        """
        from lms.djangoapps.certificates.api import get_active_web_certificate
        from openedx.core.lib.courses import course_image_url

        # Workaround for a problem discovered in https://openedx.atlassian.net/browse/TNL-2806.
        # If the course has a malformed grading policy such that
        # course._grading_policy['GRADE_CUTOFFS'] = {}, then
        # course.lowest_passing_grade will raise a ValueError.
        # Work around this for now by defaulting to None.
        try:
            lowest_passing_grade = course.lowest_passing_grade
        except ValueError:
            lowest_passing_grade = None

        display_name = course.display_name
        start = course.start
        end = course.end
        max_student_enrollments_allowed = course.max_student_enrollments_allowed
        if isinstance(course.id, CCXLocator):
            from lms.djangoapps.ccx.utils import get_ccx_from_ccx_locator
            ccx = get_ccx_from_ccx_locator(course.id)
            display_name = ccx.display_name
            start = ccx.start
            end = ccx.due
            max_student_enrollments_allowed = ccx.max_student_enrollments_allowed

        course_overview = cls.objects.filter(id=course.id)
        if course_overview.exists():
            log.info('Updating course overview for %s.', str(course.id))
            course_overview = course_overview.first()
            # MySQL ignores casing, but CourseKey doesn't. To prevent multiple
            # courses with different cased keys from overriding each other, we'll
            # check for equality here in python.
            if course_overview.id != course.id:
                raise CourseOverviewCaseMismatchException(
                    course_overview.id, course.id)
        else:
            log.info('Creating course overview for %s.', str(course.id))
            course_overview = cls()

        course_overview.version = cls.VERSION
        course_overview.id = course.id
        course_overview._location = course.location  # lint-amnesty, pylint: disable=protected-access
        course_overview.org = course.location.org
        course_overview.display_name = display_name
        course_overview.display_number_with_default = course.display_number_with_default
        course_overview.display_org_with_default = course.display_org_with_default

        course_overview.start = start
        course_overview.end = end
        course_overview.advertised_start = course.advertised_start
        course_overview.announcement = course.announcement

        course_overview.banner_image_url = course_image_url(
            course, 'banner_image')
        course_overview.course_image_url = course_image_url(course)
        course_overview.social_sharing_url = course.social_sharing_url

        updated_available_date, updated_display_behavior = CourseDetails.validate_certificate_settings(
            course.certificate_available_date,
            course.certificates_display_behavior)

        course_overview.certificates_display_behavior = updated_display_behavior
        course_overview.certificate_available_date = updated_available_date
        course_overview.certificates_show_before_end = course.certificates_show_before_end
        course_overview.cert_html_view_enabled = course.cert_html_view_enabled
        course_overview.has_any_active_web_certificate = (
            get_active_web_certificate(course) is not None)
        course_overview.cert_name_short = course.cert_name_short
        course_overview.cert_name_long = course.cert_name_long
        course_overview.lowest_passing_grade = lowest_passing_grade
        course_overview.end_of_course_survey_url = course.end_of_course_survey_url

        course_overview.days_early_for_beta = course.days_early_for_beta
        course_overview.mobile_available = course.mobile_available
        course_overview.visible_to_staff_only = course.visible_to_staff_only
        course_overview._pre_requisite_courses_json = json.dumps(
            course.pre_requisite_courses)  # lint-amnesty, pylint: disable=protected-access

        course_overview.enrollment_start = course.enrollment_start
        course_overview.enrollment_end = course.enrollment_end
        course_overview.enrollment_domain = course.enrollment_domain
        course_overview.invitation_only = course.invitation_only
        course_overview.max_student_enrollments_allowed = max_student_enrollments_allowed

        course_overview.catalog_visibility = course.catalog_visibility
        course_overview.short_description = CourseDetails.fetch_about_attribute(
            course.id, 'short_description')
        course_overview.effort = CourseDetails.fetch_about_attribute(
            course.id, 'effort')
        course_overview.course_video_url = CourseDetails.fetch_video_url(
            course.id)
        course_overview.self_paced = course.self_paced

        course_overview.has_highlights = cls._get_course_has_highlights(course)

        course_overview.enable_proctored_exams = course.enable_proctored_exams
        course_overview.proctoring_provider = course.proctoring_provider
        course_overview.proctoring_escalation_email = course.proctoring_escalation_email
        course_overview.allow_proctoring_opt_out = course.allow_proctoring_opt_out

        course_overview.entrance_exam_enabled = course.entrance_exam_enabled
        # entrance_exam_id defaults to None in the course object, but '' is more reasonable for a string field
        course_overview.entrance_exam_id = course.entrance_exam_id or ''
        # Despite it being a float, the course object defaults to an int. So we will detect that case and update
        # it to be a float like everything else.
        if isinstance(course.entrance_exam_minimum_score_pct, int):
            course_overview.entrance_exam_minimum_score_pct = course.entrance_exam_minimum_score_pct / 100
        else:
            course_overview.entrance_exam_minimum_score_pct = course.entrance_exam_minimum_score_pct

        if not CatalogIntegration.is_enabled():
            course_overview.language = course.language

        return course_overview