data.py 5.99 KB
Newer Older
1 2 3 4 5
"""
Data Aggregation Layer of the Enrollment API. Collects all enrollment specific data into a single
source to be used throughout the API.

"""
6
import logging
7 8
from django.contrib.auth.models import User
from opaque_keys.edx.keys import CourseKey
9
from xmodule.modulestore.django import modulestore
Ned Batchelder committed
10 11 12 13
from enrollment.errors import (
    CourseNotFoundError, CourseEnrollmentClosedError, CourseEnrollmentFullError,
    CourseEnrollmentExistsError, UserNotFoundError,
)
14
from enrollment.serializers import CourseEnrollmentSerializer, CourseField
Ned Batchelder committed
15 16 17 18
from student.models import (
    CourseEnrollment, NonExistentCourseError, EnrollmentClosedError,
    CourseFullError, AlreadyEnrolledError,
)
19 20

log = logging.getLogger(__name__)
21 22


23 24
def get_course_enrollments(user_id):
    """Retrieve a list representing all aggregated data for a user's course enrollments.
25

26
    Construct a representation of all course enrollment data for a specific user.
27 28

    Args:
29
        user_id (str): The name of the user to retrieve course enrollment information for.
30 31

    Returns:
32
        A serializable list of dictionaries of all aggregated enrollment data for a user.
33 34

    """
35
    qset = CourseEnrollment.objects.filter(
36
        user__username=user_id, is_active=True
37
    ).order_by('created')
38
    return CourseEnrollmentSerializer(qset).data  # pylint: disable=no-member
39 40


41 42
def get_course_enrollment(username, course_id):
    """Retrieve an object representing all aggregated data for a user's course enrollment.
43

44
    Get the course enrollment information for a specific user and course.
45 46

    Args:
47
        username (str): The name of the user to retrieve course enrollment information for.
48 49 50 51 52 53
        course_id (str): The course to retrieve course enrollment information for.

    Returns:
        A serializable dictionary representing the course enrollment.

    """
54 55 56
    course_key = CourseKey.from_string(course_id)
    try:
        enrollment = CourseEnrollment.objects.get(
57
            user__username=username, course_id=course_key
58
        )
59
        return CourseEnrollmentSerializer(enrollment).data  # pylint: disable=no-member
60 61 62 63
    except CourseEnrollment.DoesNotExist:
        return None


64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
def create_course_enrollment(username, course_id, mode, is_active):
    """Create a new course enrollment for the given user.

    Creates a new course enrollment for the specified user username.

    Args:
        username (str): The name of the user to create a new course enrollment for.
        course_id (str): The course to create the course enrollment for.
        mode (str): (Optional) The mode for the new enrollment.
        is_active (boolean): (Optional) Determines if the enrollment is active.

    Returns:
        A serializable dictionary representing the new course enrollment.

    Raises:
        CourseNotFoundError
        CourseEnrollmentFullError
        EnrollmentClosedError
        CourseEnrollmentExistsError

    """
    course_key = CourseKey.from_string(course_id)

    try:
        user = User.objects.get(username=username)
    except User.DoesNotExist:
        msg = u"Not user with username '{username}' found.".format(username=username)
        log.warn(msg)
        raise UserNotFoundError(msg)

    try:
        enrollment = CourseEnrollment.enroll(user, course_key, check_access=True)
        return _update_enrollment(enrollment, is_active=is_active, mode=mode)
    except NonExistentCourseError as err:
        raise CourseNotFoundError(err.message)
    except EnrollmentClosedError as err:
        raise CourseEnrollmentClosedError(err.message)
    except CourseFullError as err:
        raise CourseEnrollmentFullError(err.message)
    except AlreadyEnrolledError as err:
104 105
        enrollment = get_course_enrollment(username, course_id)
        raise CourseEnrollmentExistsError(err.message, enrollment)
106 107 108 109


def update_course_enrollment(username, course_id, mode=None, is_active=None):
    """Modify a course enrollment for a user.
110 111 112 113

    Allows updates to a specific course enrollment.

    Args:
114
        username (str): The name of the user to retrieve course enrollment information for.
115
        course_id (str): The course to retrieve course enrollment information for.
116
        mode (str): (Optional) If specified, modify the mode for this enrollment.
117 118 119 120 121 122
        is_active (boolean): (Optional) Determines if the enrollment is active.

    Returns:
        A serializable dictionary representing the modified course enrollment.

    """
123 124
    course_key = CourseKey.from_string(course_id)

125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
    try:
        user = User.objects.get(username=username)
    except User.DoesNotExist:
        msg = u"Not user with username '{username}' found.".format(username=username)
        log.warn(msg)
        raise UserNotFoundError(msg)

    try:
        enrollment = CourseEnrollment.objects.get(user=user, course_id=course_key)
        return _update_enrollment(enrollment, is_active=is_active, mode=mode)
    except CourseEnrollment.DoesNotExist:
        return None


def _update_enrollment(enrollment, is_active=None, mode=None):
140 141
    enrollment.update_enrollment(is_active=is_active, mode=mode)
    enrollment.save()
142
    return CourseEnrollmentSerializer(enrollment).data  # pylint: disable=no-member
143 144


145
def get_course_enrollment_info(course_id, include_expired=False):
146
    """Returns all course enrollment information for the given course.
147

148
    Based on the course id, return all related course information..
149

150 151 152
    Args:
        course_id (str): The course to retrieve enrollment information for.

153 154 155
        include_expired (bool): Boolean denoting whether expired course modes
        should be included in the returned JSON data.

156 157 158
    Returns:
        A serializable dictionary representing the course's enrollment information.

159 160 161
    Raises:
        CourseNotFoundError

162 163 164 165
    """
    course_key = CourseKey.from_string(course_id)
    course = modulestore().get_course(course_key)
    if course is None:
166 167 168
        msg = u"Requested enrollment information for unknown course {course}".format(course=course_id)
        log.warning(msg)
        raise CourseNotFoundError(msg)
169
    return CourseField().to_native(course, include_expired=include_expired)