def test_add_course_requirement_namespace(self):
        credit_course = add_credit_course(self.course_key)
        requirement = {
            "namespace": "grade",
            "name": "grade",
            "display_name": "Grade",
            "criteria": {
                "min_grade": 0.8
            },
        }
        credit_req, created = CreditRequirement.add_or_update_course_requirement(
            credit_course, requirement, 0)
        assert credit_course == credit_req.course
        assert created is True

        requirement = {
            "namespace": "new_grade",
            "name": "new_grade",
            "display_name": "New Grade",
            "criteria": {},
        }
        credit_req, created = CreditRequirement.add_or_update_course_requirement(
            credit_course, requirement, 1)
        assert credit_course == credit_req.course
        assert created is True

        requirements = CreditRequirement.get_course_requirements(
            self.course_key)
        assert len(requirements) == 2

        requirements = CreditRequirement.get_course_requirements(
            self.course_key, namespace="grade")
        assert len(requirements) == 1
예제 #2
0
    def test_add_course_requirement_namespace(self):
        credit_course = add_credit_course(self.course_key)
        requirement = {
            "namespace": "grade",
            "name": "grade",
            "display_name": "Grade",
            "criteria": {
                "min_grade": 0.8
            },
        }
        credit_req, created = CreditRequirement.add_or_update_course_requirement(credit_course, requirement, 0)
        self.assertEqual(credit_course, credit_req.course)
        self.assertEqual(created, True)

        requirement = {
            "namespace": "new_grade",
            "name": "new_grade",
            "display_name": "New Grade",
            "criteria": {},
        }
        credit_req, created = CreditRequirement.add_or_update_course_requirement(credit_course, requirement, 1)
        self.assertEqual(credit_course, credit_req.course)
        self.assertEqual(created, True)

        requirements = CreditRequirement.get_course_requirements(self.course_key)
        self.assertEqual(len(requirements), 2)

        requirements = CreditRequirement.get_course_requirements(self.course_key, namespace="grade")
        self.assertEqual(len(requirements), 1)
예제 #3
0
    def test_add_course_requirement_namespace(self):
        credit_course = self.add_credit_course()
        requirement = {
            "namespace": "grade",
            "name": "grade",
            "criteria": {
                "min_grade": 0.8
            }
        }
        credit_req, created = CreditRequirement.add_or_update_course_requirement(
            credit_course, requirement)
        self.assertEqual(credit_course, credit_req.course)
        self.assertEqual(created, True)

        requirement = {"namespace": "icrv", "name": "midterm", "criteria": ""}
        credit_req, created = CreditRequirement.add_or_update_course_requirement(
            credit_course, requirement)
        self.assertEqual(credit_course, credit_req.course)
        self.assertEqual(created, True)

        requirements = CreditRequirement.get_course_requirements(
            self.course_key)
        self.assertEqual(len(requirements), 2)
        requirements = CreditRequirement.get_course_requirements(
            self.course_key, namespace="grade")
        self.assertEqual(len(requirements), 1)
예제 #4
0
    def test_add_course_requirement_namespace(self):
        credit_course = self.add_credit_course()
        requirement = {
            "namespace": "grade",
            "name": "grade",
            "display_name": "Grade",
            "criteria": {
                "min_grade": 0.8
            },
        }
        credit_req, created = CreditRequirement.add_or_update_course_requirement(
            credit_course, requirement, 0)
        self.assertEqual(credit_course, credit_req.course)
        self.assertEqual(created, True)

        requirement = {
            "namespace": "reverification",
            "name": "i4x://edX/DemoX/edx-reverification-block/assessment_uuid",
            "display_name": "Assessment 1",
            "criteria": {},
        }
        credit_req, created = CreditRequirement.add_or_update_course_requirement(
            credit_course, requirement, 1)
        self.assertEqual(credit_course, credit_req.course)
        self.assertEqual(created, True)

        requirements = CreditRequirement.get_course_requirements(
            self.course_key)
        self.assertEqual(len(requirements), 2)

        requirements = CreditRequirement.get_course_requirements(
            self.course_key, namespace="grade")
        self.assertEqual(len(requirements), 1)
예제 #5
0
    def test_add_course_requirement_namespace(self):
        credit_course = self.add_credit_course()
        requirement = {
            "namespace": "grade",
            "name": "grade",
            "criteria": {
                "min_grade": 0.8
            }
        }
        credit_req, created = CreditRequirement.add_or_update_course_requirement(credit_course, requirement)
        self.assertEqual(credit_course, credit_req.course)
        self.assertEqual(created, True)

        requirement = {
            "namespace": "icrv",
            "name": "midterm",
            "criteria": ""
        }
        credit_req, created = CreditRequirement.add_or_update_course_requirement(credit_course, requirement)
        self.assertEqual(credit_course, credit_req.course)
        self.assertEqual(created, True)

        requirements = CreditRequirement.get_course_requirements(self.course_key)
        self.assertEqual(len(requirements), 2)
        requirements = CreditRequirement.get_course_requirements(self.course_key, namespace="grade")
        self.assertEqual(len(requirements), 1)
예제 #6
0
    def test_add_course_requirement_namespace(self):
        credit_course = self.add_credit_course()
        requirement = {
            "namespace": "grade",
            "name": "grade",
            "display_name": "Grade",
            "criteria": {
                "min_grade": 0.8
            }
        }
        credit_req, created = CreditRequirement.add_or_update_course_requirement(credit_course, requirement)
        self.assertEqual(credit_course, credit_req.course)
        self.assertEqual(created, True)

        requirement = {
            "namespace": "reverification",
            "name": "i4x://edX/DemoX/edx-reverification-block/assessment_uuid",
            "display_name": "Assessment 1",
            "criteria": {}
        }
        credit_req, created = CreditRequirement.add_or_update_course_requirement(credit_course, requirement)
        self.assertEqual(credit_course, credit_req.course)
        self.assertEqual(created, True)

        requirements = CreditRequirement.get_course_requirements(self.course_key)
        self.assertEqual(len(requirements), 2)

        requirements = CreditRequirement.get_course_requirements(self.course_key, namespace="grade")
        self.assertEqual(len(requirements), 1)
예제 #7
0
    def test_add_course_requirement_namespace(self):
        credit_course = add_credit_course(self.course_key)
        requirement = {
            "namespace": "grade",
            "name": "grade",
            "display_name": "Grade",
            "criteria": {
                "min_grade": 0.8
            },
        }
        credit_req, created = CreditRequirement.add_or_update_course_requirement(credit_course, requirement, 0)
        self.assertEqual(credit_course, credit_req.course)
        self.assertEqual(created, True)

        requirement = {
            "namespace": "new_grade",
            "name": "new_grade",
            "display_name": "New Grade",
            "criteria": {},
        }
        credit_req, created = CreditRequirement.add_or_update_course_requirement(credit_course, requirement, 1)
        self.assertEqual(credit_course, credit_req.course)
        self.assertEqual(created, True)

        requirements = CreditRequirement.get_course_requirements(self.course_key)
        self.assertEqual(len(requirements), 2)

        requirements = CreditRequirement.get_course_requirements(self.course_key, namespace="grade")
        self.assertEqual(len(requirements), 1)
예제 #8
0
def set_credit_requirements(course_key, requirements):
    """
    Add requirements to given course.

    Args:
        course_key(CourseKey): The identifier for course
        requirements(list): List of requirements to be added

    Example:
        >>> set_credit_requirements(
                "course-v1-edX-DemoX-1T2015",
                [
                    {
                        "namespace": "reverification",
                        "name": "i4x://edX/DemoX/edx-reverification-block/assessment_uuid",
                        "display_name": "Assessment 1",
                        "criteria": {},
                    },
                    {
                        "namespace": "proctored_exam",
                        "name": "i4x://edX/DemoX/proctoring-block/final_uuid",
                        "display_name": "Final Exam",
                        "criteria": {},
                    },
                    {
                        "namespace": "grade",
                        "name": "grade",
                        "display_name": "Grade",
                        "criteria": {"min_grade": 0.8},
                    },
                ])

    Raises:
        InvalidCreditRequirements

    Returns:
        None
    """

    invalid_requirements = _validate_requirements(requirements)
    if invalid_requirements:
        invalid_requirements = ", ".join(invalid_requirements)
        raise InvalidCreditRequirements(invalid_requirements)

    try:
        credit_course = CreditCourse.get_credit_course(course_key=course_key)
    except CreditCourse.DoesNotExist:
        raise InvalidCreditCourse()

    old_requirements = CreditRequirement.get_course_requirements(
        course_key=course_key)
    requirements_to_disable = _get_requirements_to_disable(
        old_requirements, requirements)
    if requirements_to_disable:
        CreditRequirement.disable_credit_requirements(requirements_to_disable)

    for order, requirement in enumerate(requirements):
        CreditRequirement.add_or_update_course_requirement(
            credit_course, requirement, order)
예제 #9
0
def set_credit_requirements(course_key, requirements):
    """
    Add requirements to given course.

    Args:
        course_key(CourseKey): The identifier for course
        requirements(list): List of requirements to be added

    Example:
        >>> set_credit_requirements(
                "course-v1-edX-DemoX-1T2015",
                [
                    {
                        "namespace": "reverification",
                        "name": "i4x://edX/DemoX/edx-reverification-block/assessment_uuid",
                        "display_name": "Assessment 1",
                        "criteria": {},
                    },
                    {
                        "namespace": "proctored_exam",
                        "name": "i4x://edX/DemoX/proctoring-block/final_uuid",
                        "display_name": "Final Exam",
                        "criteria": {},
                    },
                    {
                        "namespace": "grade",
                        "name": "grade",
                        "display_name": "Grade",
                        "criteria": {"min_grade": 0.8},
                    },
                ])

    Raises:
        InvalidCreditRequirements

    Returns:
        None
    """

    invalid_requirements = _validate_requirements(requirements)
    if invalid_requirements:
        invalid_requirements = ", ".join(invalid_requirements)
        raise InvalidCreditRequirements(invalid_requirements)

    try:
        credit_course = CreditCourse.get_credit_course(course_key=course_key)
    except CreditCourse.DoesNotExist:
        raise InvalidCreditCourse()

    old_requirements = CreditRequirement.get_course_requirements(course_key=course_key)
    requirements_to_disable = _get_requirements_to_disable(old_requirements, requirements)
    if requirements_to_disable:
        CreditRequirement.disable_credit_requirements(requirements_to_disable)

    for order, requirement in enumerate(requirements):
        CreditRequirement.add_or_update_course_requirement(credit_course, requirement, order)
예제 #10
0
 def test_get_course_requirements(self):
     credit_course = self.add_credit_course()
     requirement = {
         "namespace": "grade",
         "name": "grade",
         "display_name": "Grade",
         "criteria": {
             "min_grade": 0.8
         }
     }
     credit_req, created = CreditRequirement.add_or_update_course_requirement(credit_course, requirement)
     self.assertEqual(credit_course, credit_req.course)
     self.assertEqual(created, True)
     requirements = CreditRequirement.get_course_requirements(self.course_key)
     self.assertEqual(len(requirements), 1)
    def add_course_requirements(self):
        """
        Add requirements to course.
        """
        requirements = ({
            "namespace": "grade",
            "name": "grade",
            "display_name": "Grade",
            "criteria": {
                "min_grade": 0.8
            }
        }, {
            "namespace": "new_grade",
            "name": "new_grade",
            "display_name": "new_grade",
            "criteria": {
                "min_grade": 0.8
            },
        })

        for i, requirement in enumerate(requirements):
            credit_requirement, _ = CreditRequirement.add_or_update_course_requirement(
                self.credit_course, requirement, i)
            CreditRequirementStatus.add_or_update_requirement_status(
                self.old_username, credit_requirement, "satisfied",
                {"final_grade": 0.95})
예제 #12
0
def get_credit_requirement_status(course_key, username, namespace=None, name=None):
    """ Retrieve the user's status for each credit requirement in the course.

    Args:
        course_key (CourseKey): The identifier for course
        username (str): The identifier of the user

    Example:
        >>> get_credit_requirement_status("course-v1-edX-DemoX-1T2015", "john")

                [
                    {
                        "namespace": "reverification",
                        "name": "i4x://edX/DemoX/edx-reverification-block/assessment_uuid",
                        "display_name": "In Course Reverification",
                        "criteria": {},
                        "reason": {},
                        "status": "failed",
                        "status_date": "2015-06-26 07:49:13",
                    },
                    {
                        "namespace": "proctored_exam",
                        "name": "i4x://edX/DemoX/proctoring-block/final_uuid",
                        "display_name": "Proctored Mid Term Exam",
                        "criteria": {},
                        "reason": {},
                        "status": "satisfied",
                        "status_date": "2015-06-26 11:07:42",
                    },
                    {
                        "namespace": "grade",
                        "name": "i4x://edX/DemoX/proctoring-block/final_uuid",
                        "display_name": "Minimum Passing Grade",
                        "criteria": {"min_grade": 0.8},
                        "reason": {"final_grade": 0.95},
                        "status": "satisfied",
                        "status_date": "2015-06-26 11:07:44",
                    },
                ]

    Returns:
        list of requirement statuses
    """
    requirements = CreditRequirement.get_course_requirements(course_key, namespace=namespace, name=name)
    requirement_statuses = CreditRequirementStatus.get_statuses(requirements, username)
    requirement_statuses = dict((o.requirement, o) for o in requirement_statuses)
    statuses = []
    for requirement in requirements:
        requirement_status = requirement_statuses.get(requirement)
        statuses.append({
            "namespace": requirement.namespace,
            "name": requirement.name,
            "display_name": requirement.display_name,
            "criteria": requirement.criteria,
            "reason": requirement_status.reason if requirement_status else None,
            "status": requirement_status.status if requirement_status else None,
            "status_date": requirement_status.modified if requirement_status else None,
        })
    return statuses
예제 #13
0
 def test_get_course_requirements(self):
     credit_course = self.add_credit_course()
     requirement = {
         "namespace": "grade",
         "name": "grade",
         "display_name": "Grade",
         "criteria": {
             "min_grade": 0.8
         }
     }
     credit_req, created = CreditRequirement.add_or_update_course_requirement(
         credit_course, requirement)
     self.assertEqual(credit_course, credit_req.course)
     self.assertEqual(created, True)
     requirements = CreditRequirement.get_course_requirements(
         self.course_key)
     self.assertEqual(len(requirements), 1)
def get_credit_requirement_status(course_key, username, namespace=None, name=None):
    """ Retrieve the user's status for each credit requirement in the course.

    Args:
        course_key (CourseKey): The identifier for course
        username (str): The identifier of the user

    Example:
        >>> get_credit_requirement_status("course-v1-edX-DemoX-1T2015", "john")

                [
                    {
                        "namespace": "proctored_exam",
                        "name": "i4x://edX/DemoX/proctoring-block/final_uuid",
                        "display_name": "Proctored Mid Term Exam",
                        "criteria": {},
                        "reason": {},
                        "status": "satisfied",
                        "status_date": "2015-06-26 11:07:42",
                        "order": 1,
                    },
                    {
                        "namespace": "grade",
                        "name": "i4x://edX/DemoX/proctoring-block/final_uuid",
                        "display_name": "Minimum Passing Grade",
                        "criteria": {"min_grade": 0.8},
                        "reason": {"final_grade": 0.95},
                        "status": "satisfied",
                        "status_date": "2015-06-26 11:07:44",
                        "order": 2,
                    },
                ]

    Returns:
        list of requirement statuses
    """
    requirements = CreditRequirement.get_course_requirements(course_key, namespace=namespace, name=name)
    requirement_statuses = CreditRequirementStatus.get_statuses(requirements, username)
    requirement_statuses = {o.requirement: o for o in requirement_statuses}
    statuses = []
    for requirement in requirements:
        requirement_status = requirement_statuses.get(requirement)
        statuses.append({
            "namespace": requirement.namespace,
            "name": requirement.name,
            "display_name": requirement.display_name,
            "criteria": requirement.criteria,
            "reason": requirement_status.reason if requirement_status else None,
            "status": requirement_status.status if requirement_status else None,
            "status_date": requirement_status.modified if requirement_status else None,
            # We retain the old name "order" in the API because changing APIs takes a lot more coordination.
            "order": requirement.sort_value,
        })
    return statuses
예제 #15
0
    def test_set_credit_requirement_status(self):
        self.add_credit_course()
        requirements = [
            {
                "namespace": "grade",
                "name": "grade",
                "display_name": "Grade",
                "criteria": {
                    "min_grade": 0.8
                }
            },
            {
                "namespace": "reverification",
                "name": "i4x://edX/DemoX/edx-reverification-block/assessment_uuid",
                "display_name": "Assessment 1",
                "criteria": {}
            }
        ]

        set_credit_requirements(self.course_key, requirements)
        course_requirements = CreditRequirement.get_course_requirements(self.course_key)
        self.assertEqual(len(course_requirements), 2)

        requirement = get_credit_requirement(self.course_key, "grade", "grade")
        set_credit_requirement_status("staff", requirement, 'satisfied', {})
        course_requirement = CreditRequirement.get_course_requirement(
            requirement['course_key'], requirement['namespace'], requirement['name']
        )
        status = CreditRequirementStatus.objects.get(username="******", requirement=course_requirement)
        self.assertEqual(status.requirement.namespace, requirement['namespace'])
        self.assertEqual(status.status, "satisfied")

        set_credit_requirement_status(
            "staff", requirement, 'failed', {'failure_reason': "requirements not satisfied"}
        )
        status = CreditRequirementStatus.objects.get(username="******", requirement=course_requirement)
        self.assertEqual(status.requirement.namespace, requirement['namespace'])
        self.assertEqual(status.status, "failed")
예제 #16
0
def remove_credit_requirement_status(username, course_key, req_namespace, req_name):
    """
    Remove the user's requirement status.

    This will remove the record from the credit requirement status table.
    The user will still be eligible for the credit in a course.

    Args:
        username (str): Username of the user
        course_key (CourseKey): Identifier for the course associated
                                with the requirement.
        req_namespace (str): Namespace of the requirement
                            (e.g. "grade" or "reverification")
        req_name (str): Name of the requirement
                        (e.g. "grade" or the location of the ICRV XBlock)

    Example:
        >>> remove_credit_requirement_status(
                "staff",
                CourseKey.from_string("course-v1-edX-DemoX-1T2015"),
                "reverification",
                "i4x://edX/DemoX/edx-reverification-block/assessment_uuid".
            )

    """

    # Find the requirement we're trying to remove
    req_to_remove = CreditRequirement.get_course_requirements(course_key, namespace=req_namespace, name=req_name)

    # If we can't find the requirement, then the most likely explanation
    # is that there was a lag removing the credit requirements after the course
    # was published.  We *could* attempt to remove the requirement here,
    # but that could cause serious performance issues if many users attempt to
    # lock the row at the same time.
    # Instead, we skip removing the requirement and log an error.
    if not req_to_remove:
        log.error(
            (
                u'Could not remove credit requirement in course "%s" '
                u'with namespace "%s" and name "%s" '
                u'because the requirement does not exist. '
            ),
            unicode(course_key), req_namespace, req_name
        )
        return

    # Remove the requirement status
    CreditRequirementStatus.remove_requirement_status(
        username, req_to_remove
    )
예제 #17
0
    def test_requirements_to_disable(self):
        self.add_credit_course()
        requirements = [
            {
                "namespace": "grade",
                "name": "grade",
                "criteria": {
                    "min_grade": 0.8
                }
            },
            {
                "namespace": "grade",
                "name": "grade",
                "criteria": {
                    "min_grade": 0.8
                }
            }
        ]

        set_credit_requirements(self.course_key, requirements)
        old_requirements = CreditRequirement.get_course_requirements(self.course_key)
        self.assertEqual(len(old_requirements), 1)

        requirements = [
            {
                "namespace": "reverification",
                "name": "midterm",
                "criteria": {}
            }
        ]
        requirements_to_disabled = _get_requirements_to_disable(old_requirements, requirements)
        self.assertEqual(len(requirements_to_disabled), 1)
        self.assertEqual(requirements_to_disabled[0], old_requirements[0].id)

        requirements = [
            {
                "namespace": "grade",
                "name": "grade",
                "criteria": {
                    "min_grade": 0.8
                }
            },
            {
                "namespace": "reverification",
                "name": "midterm",
                "criteria": {}
            }
        ]
        requirements_to_disabled = _get_requirements_to_disable(old_requirements, requirements)
        self.assertEqual(len(requirements_to_disabled), 0)
예제 #18
0
def get_credit_requirements(course_key, namespace=None):
    """
    Get credit eligibility requirements of a given course and namespace.

    Args:
        course_key(CourseKey): The identifier for course
        namespace(str): Namespace of requirements

    Example:
        >>> get_credit_requirements("course-v1-edX-DemoX-1T2015")
            {
                requirements =
                [
                    {
                        "namespace": "reverification",
                        "name": "i4x://edX/DemoX/edx-reverification-block/assessment_uuid",
                        "display_name": "Assessment 1",
                        "criteria": {},
                    },
                    {
                        "namespace": "proctored_exam",
                        "name": "i4x://edX/DemoX/proctoring-block/final_uuid",
                        "display_name": "Final Exam",
                        "criteria": {},
                    },
                    {
                        "namespace": "grade",
                        "name": "grade",
                        "display_name": "Grade",
                        "criteria": {"min_grade": 0.8},
                    },
                ]
            }

    Returns:
        Dict of requirements in the given namespace

    """

    requirements = CreditRequirement.get_course_requirements(course_key, namespace)
    return [
        {
            "namespace": requirement.namespace,
            "name": requirement.name,
            "display_name": requirement.display_name,
            "criteria": requirement.criteria
        }
        for requirement in requirements
    ]
예제 #19
0
    def test_requirements_to_disable(self):
        self.add_credit_course()
        requirements = [
            {
                "namespace": "grade",
                "name": "grade",
                "display_name": "Grade",
                "criteria": {
                    "min_grade": 0.8
                }
            }
        ]

        set_credit_requirements(self.course_key, requirements)
        old_requirements = CreditRequirement.get_course_requirements(self.course_key)
        self.assertEqual(len(old_requirements), 1)

        requirements = [
            {
                "namespace": "reverification",
                "name": "i4x://edX/DemoX/edx-reverification-block/assessment_uuid",
                "display_name": "Assessment 1",
                "criteria": {}
            }
        ]
        requirements_to_disabled = _get_requirements_to_disable(old_requirements, requirements)
        self.assertEqual(len(requirements_to_disabled), 1)
        self.assertEqual(requirements_to_disabled[0], old_requirements[0].id)

        requirements = [
            {
                "namespace": "grade",
                "name": "grade",
                "display_name": "Grade",
                "criteria": {
                    "min_grade": 0.8
                }
            },
            {
                "namespace": "reverification",
                "name": "i4x://edX/DemoX/edx-reverification-block/assessment_uuid",
                "display_name": "Assessment 1",
                "criteria": {}
            }
        ]
        requirements_to_disabled = _get_requirements_to_disable(old_requirements, requirements)
        self.assertEqual(len(requirements_to_disabled), 0)
예제 #20
0
    def test_requirements_to_disable(self):
        self.add_credit_course()
        requirements = [{
            "namespace": "grade",
            "name": "grade",
            "criteria": {
                "min_grade": 0.8
            }
        }, {
            "namespace": "grade",
            "name": "grade",
            "criteria": {
                "min_grade": 0.8
            }
        }]

        set_credit_requirements(self.course_key, requirements)
        old_requirements = CreditRequirement.get_course_requirements(
            self.course_key)
        self.assertEqual(len(old_requirements), 1)

        requirements = [{
            "namespace": "reverification",
            "name": "midterm",
            "criteria": {}
        }]
        requirements_to_disabled = _get_requirements_to_disable(
            old_requirements, requirements)
        self.assertEqual(len(requirements_to_disabled), 1)
        self.assertEqual(requirements_to_disabled[0], old_requirements[0].id)

        requirements = [{
            "namespace": "grade",
            "name": "grade",
            "criteria": {
                "min_grade": 0.8
            }
        }, {
            "namespace": "reverification",
            "name": "midterm",
            "criteria": {}
        }]
        requirements_to_disabled = _get_requirements_to_disable(
            old_requirements, requirements)
        self.assertEqual(len(requirements_to_disabled), 0)
예제 #21
0
    def add_course_requirements(self):
        """
        Add requirements to course.
        """
        requirements = (
            {
                "namespace": "grade",
                "name": "grade",
                "display_name": "Grade",
                "criteria": {
                    "min_grade": 0.8
                }
            },
            {
                "namespace": "new_grade",
                "name": "new_grade",
                "display_name": "new_grade",
                "criteria": {
                    "min_grade": 0.8
                },
            }
        )

        for i, requirement in enumerate(requirements):
            credit_requirement, _ = CreditRequirement.add_or_update_course_requirement(
                self.credit_course,
                requirement,
                i
            )
            CreditRequirementStatus.add_or_update_requirement_status(
                self.old_username,
                credit_requirement,
                "satisfied",
                {
                    "final_grade": 0.95
                }
            )
예제 #22
0
def set_credit_requirement_status(user,
                                  course_key,
                                  req_namespace,
                                  req_name,
                                  status="satisfied",
                                  reason=None):
    """
    Update the user's requirement status.

    This will record whether the user satisfied or failed a particular requirement
    in a course.  If the user has satisfied all requirements, the user will be marked
    as eligible for credit in the course.

    Args:
        user(User): User object to set credit requirement for.
        course_key (CourseKey): Identifier for the course associated with the requirement.
        req_namespace (str): Namespace of the requirement (e.g. "grade" or "reverification")
        req_name (str): Name of the requirement (e.g. "grade" or the location of the ICRV XBlock)

    Keyword Arguments:
        status (str): Status of the requirement (either "satisfied" or "failed")
        reason (dict): Reason of the status
    """
    # Check whether user has credit eligible enrollment.
    enrollment_mode, is_active = CourseEnrollment.enrollment_mode_for_user(
        user, course_key)
    has_credit_eligible_enrollment = (
        CourseMode.is_credit_eligible_slug(enrollment_mode) and is_active)

    # Refuse to set status of requirement if the user enrollment is not credit eligible.
    if not has_credit_eligible_enrollment:
        return

    # Do not allow students who have requested credit to change their eligibility
    if CreditRequest.get_user_request_status(user.username, course_key):
        log.info(
            u'Refusing to set status of requirement with namespace "%s" and name "%s" because the '
            u'user "%s" has already requested credit for the course "%s".',
            req_namespace, req_name, user.username, course_key)
        return

    # Do not allow a student who has earned eligibility to un-earn eligibility
    eligible_before_update = CreditEligibility.is_user_eligible_for_credit(
        course_key, user.username)
    if eligible_before_update and status == 'failed':
        log.info(
            u'Refusing to set status of requirement with namespace "%s" and name "%s" to "failed" because the '
            u'user "%s" is already eligible for credit in the course "%s".',
            req_namespace, req_name, user.username, course_key)
        return

    # Retrieve all credit requirements for the course
    # We retrieve all of them to avoid making a second query later when
    # we need to check whether all requirements have been satisfied.
    reqs = CreditRequirement.get_course_requirements(course_key)

    # Find the requirement we're trying to set
    req_to_update = next(
        (req for req in reqs
         if req.namespace == req_namespace and req.name == req_name), None)

    # If we can't find the requirement, then the most likely explanation
    # is that there was a lag updating the credit requirements after the course
    # was published.  We *could* attempt to create the requirement here,
    # but that could cause serious performance issues if many users attempt to
    # lock the row at the same time.
    # Instead, we skip updating the requirement and log an error.
    if req_to_update is None:
        log.error(
            (u'Could not update credit requirement in course "%s" '
             u'with namespace "%s" and name "%s" '
             u'because the requirement does not exist. '
             u'The user "%s" should have had his/her status updated to "%s".'),
            unicode(course_key), req_namespace, req_name, user.username,
            status)
        return

    # Update the requirement status
    CreditRequirementStatus.add_or_update_requirement_status(user.username,
                                                             req_to_update,
                                                             status=status,
                                                             reason=reason)

    # If we're marking this requirement as "satisfied", there's a chance that the user has met all eligibility
    # requirements, and should be notified. However, if the user was already eligible, do not send another notification.
    if status == "satisfied" and not eligible_before_update:
        is_eligible, eligibility_record_created = CreditEligibility.update_eligibility(
            reqs, user.username, course_key)
        if eligibility_record_created and is_eligible:
            try:
                send_credit_notifications(user.username, course_key)
            except Exception:  # pylint: disable=broad-except
                log.exception("Error sending email")
예제 #23
0
def get_credit_requirement_status(course_key, username, namespace=None, name=None):
    """ Retrieve the user's status for each credit requirement in the course.

    Args:
        course_key (CourseKey): The identifier for course
        username (str): The identifier of the user

    Example:
        >>> get_credit_requirement_status("course-v1-edX-DemoX-1T2015", "john")

                [
                    {
                        "namespace": "reverification",
                        "name": "i4x://edX/DemoX/edx-reverification-block/assessment_uuid",
                        "display_name": "In Course Reverification",
                        "criteria": {},
                        "reason": {},
                        "status": "failed",
                        "status_date": "2015-06-26 07:49:13",
                        "order": 0,
                    },
                    {
                        "namespace": "proctored_exam",
                        "name": "i4x://edX/DemoX/proctoring-block/final_uuid",
                        "display_name": "Proctored Mid Term Exam",
                        "criteria": {},
                        "reason": {},
                        "status": "satisfied",
                        "status_date": "2015-06-26 11:07:42",
                        "order": 1,
                    },
                    {
                        "namespace": "grade",
                        "name": "i4x://edX/DemoX/proctoring-block/final_uuid",
                        "display_name": "Minimum Passing Grade",
                        "criteria": {"min_grade": 0.8},
                        "reason": {"final_grade": 0.95},
                        "status": "satisfied",
                        "status_date": "2015-06-26 11:07:44",
                        "order": 2,
                    },
                ]

    Returns:
        list of requirement statuses
    """
    requirements = CreditRequirement.get_course_requirements(course_key, namespace=namespace, name=name)
    requirement_statuses = CreditRequirementStatus.get_statuses(requirements, username)
    requirement_statuses = dict((o.requirement, o) for o in requirement_statuses)
    statuses = []
    for requirement in requirements:
        requirement_status = requirement_statuses.get(requirement)
        statuses.append({
            "namespace": requirement.namespace,
            "name": requirement.name,
            "display_name": requirement.display_name,
            "criteria": requirement.criteria,
            "reason": requirement_status.reason if requirement_status else None,
            "status": requirement_status.status if requirement_status else None,
            "status_date": requirement_status.modified if requirement_status else None,
            "order": requirement.order,
        })
    return statuses
예제 #24
0
def set_credit_requirement_status(user, course_key, req_namespace, req_name, status="satisfied", reason=None):
    """
    Update the user's requirement status.

    This will record whether the user satisfied or failed a particular requirement
    in a course.  If the user has satisfied all requirements, the user will be marked
    as eligible for credit in the course.

    Args:
        user(User): User object to set credit requirement for.
        course_key (CourseKey): Identifier for the course associated with the requirement.
        req_namespace (str): Namespace of the requirement (e.g. "grade" or "reverification")
        req_name (str): Name of the requirement (e.g. "grade" or the location of the ICRV XBlock)

    Keyword Arguments:
        status (str): Status of the requirement (either "satisfied" or "failed")
        reason (dict): Reason of the status
    """
    # Check whether user has credit eligible enrollment.
    enrollment_mode, is_active = CourseEnrollment.enrollment_mode_for_user(user, course_key)
    has_credit_eligible_enrollment = (CourseMode.is_credit_eligible_slug(enrollment_mode) and is_active)

    # Refuse to set status of requirement if the user enrollment is not credit eligible.
    if not has_credit_eligible_enrollment:
        return

    # Do not allow students who have requested credit to change their eligibility
    if CreditRequest.get_user_request_status(user.username, course_key):
        log.info(
            u'Refusing to set status of requirement with namespace "%s" and name "%s" because the '
            u'user "%s" has already requested credit for the course "%s".',
            req_namespace, req_name, user.username, course_key
        )
        return

    # Do not allow a student who has earned eligibility to un-earn eligibility
    eligible_before_update = CreditEligibility.is_user_eligible_for_credit(course_key, user.username)
    if eligible_before_update and status == 'failed':
        log.info(
            u'Refusing to set status of requirement with namespace "%s" and name "%s" to "failed" because the '
            u'user "%s" is already eligible for credit in the course "%s".',
            req_namespace, req_name, user.username, course_key
        )
        return

    # Retrieve all credit requirements for the course
    # We retrieve all of them to avoid making a second query later when
    # we need to check whether all requirements have been satisfied.
    reqs = CreditRequirement.get_course_requirements(course_key)

    # Find the requirement we're trying to set
    req_to_update = next((
        req for req in reqs
        if req.namespace == req_namespace and req.name == req_name
    ), None)

    # If we can't find the requirement, then the most likely explanation
    # is that there was a lag updating the credit requirements after the course
    # was published.  We *could* attempt to create the requirement here,
    # but that could cause serious performance issues if many users attempt to
    # lock the row at the same time.
    # Instead, we skip updating the requirement and log an error.
    if req_to_update is None:
        log.error(
            (
                u'Could not update credit requirement in course "%s" '
                u'with namespace "%s" and name "%s" '
                u'because the requirement does not exist. '
                u'The user "%s" should have had his/her status updated to "%s".'
            ),
            unicode(course_key), req_namespace, req_name, user.username, status
        )
        return

    # Update the requirement status
    CreditRequirementStatus.add_or_update_requirement_status(
        user.username, req_to_update, status=status, reason=reason
    )

    # If we're marking this requirement as "satisfied", there's a chance that the user has met all eligibility
    # requirements, and should be notified. However, if the user was already eligible, do not send another notification.
    if status == "satisfied" and not eligible_before_update:
        is_eligible, eligibility_record_created = CreditEligibility.update_eligibility(reqs, user.username, course_key)
        if eligibility_record_created and is_eligible:
            try:
                send_credit_notifications(user.username, course_key)
            except Exception:  # pylint: disable=broad-except
                log.exception("Error sending email")
예제 #25
0
def set_credit_requirement_status(username, course_key, req_namespace, req_name, status="satisfied", reason=None):
    """
    Update the user's requirement status.

    This will record whether the user satisfied or failed a particular requirement
    in a course.  If the user has satisfied all requirements, the user will be marked
    as eligible for credit in the course.

    Args:
        username (str): Username of the user
        course_key (CourseKey): Identifier for the course associated with the requirement.
        req_namespace (str): Namespace of the requirement (e.g. "grade" or "reverification")
        req_name (str): Name of the requirement (e.g. "grade" or the location of the ICRV XBlock)

    Keyword Arguments:
        status (str): Status of the requirement (either "satisfied" or "failed")
        reason (dict): Reason of the status

    Example:
        >>> set_credit_requirement_status(
                "staff",
                CourseKey.from_string("course-v1-edX-DemoX-1T2015"),
                "reverification",
                "i4x://edX/DemoX/edx-reverification-block/assessment_uuid",
                status="satisfied",
                reason={}
            )

    """
    # Check if we're already eligible for credit.
    # If so, short-circuit this process.
    if CreditEligibility.is_user_eligible_for_credit(course_key, username):
        log.info(
            u'Skipping update of credit requirement with namespace "%s" '
            u'and name "%s" because the user "%s" is already eligible for credit '
            u'in the course "%s".',
            req_namespace, req_name, username, course_key
        )
        return

    # Retrieve all credit requirements for the course
    # We retrieve all of them to avoid making a second query later when
    # we need to check whether all requirements have been satisfied.
    reqs = CreditRequirement.get_course_requirements(course_key)

    # Find the requirement we're trying to set
    req_to_update = next((
        req for req in reqs
        if req.namespace == req_namespace and req.name == req_name
    ), None)

    # If we can't find the requirement, then the most likely explanation
    # is that there was a lag updating the credit requirements after the course
    # was published.  We *could* attempt to create the requirement here,
    # but that could cause serious performance issues if many users attempt to
    # lock the row at the same time.
    # Instead, we skip updating the requirement and log an error.
    if req_to_update is None:
        log.error(
            (
                u'Could not update credit requirement in course "%s" '
                u'with namespace "%s" and name "%s" '
                u'because the requirement does not exist. '
                u'The user "%s" should have had his/her status updated to "%s".'
            ),
            unicode(course_key), req_namespace, req_name, username, status
        )
        return

    # Update the requirement status
    CreditRequirementStatus.add_or_update_requirement_status(
        username, req_to_update, status=status, reason=reason
    )

    # If we're marking this requirement as "satisfied", there's a chance
    # that the user has met all eligibility requirements.
    if status == "satisfied":
        is_eligible, eligibility_record_created = CreditEligibility.update_eligibility(reqs, username, course_key)
        if eligibility_record_created and is_eligible:
            try:
                send_credit_notifications(username, course_key)
            except Exception:  # pylint: disable=broad-except
                log.error("Error sending email")