101 lines
4.2 KiB
Python
101 lines
4.2 KiB
Python
"""
|
|
Utils for use in enrollment codebase such as views.
|
|
"""
|
|
import logging
|
|
|
|
from django.core.exceptions import ObjectDoesNotExist # lint-amnesty, pylint: disable=wrong-import-order
|
|
from django.db import transaction
|
|
|
|
from common.djangoapps.student.models import User
|
|
from openedx.core.djangoapps.enrollments import api as enrollment_api
|
|
from openedx.core.djangoapps.enrollments.errors import CourseEnrollmentError, CourseEnrollmentExistsError
|
|
from openedx.core.lib.log_utils import audit_log
|
|
from openedx.features.enterprise_support.enrollments.exceptions import (
|
|
CourseIdMissingException,
|
|
UserDoesNotExistException
|
|
)
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
def lms_enroll_user_in_course(
|
|
username,
|
|
course_id,
|
|
mode,
|
|
enterprise_uuid,
|
|
is_active=True,
|
|
):
|
|
"""
|
|
Enrollment function meant to be called by edx-enterprise to replace the
|
|
current uses of the EnrollmentApiClient
|
|
The REST enrollment endpoint may also eventually also want to reuse this function
|
|
since it's a subset of what the endpoint handles
|
|
|
|
Unlike the REST endpoint, this function does not check for enterprise enabled, or user api key
|
|
permissions etc. Those concerns are still going to be used by REST endpoint but this function
|
|
is meant for use from within edx-enterprise hence already presume such privileges.
|
|
|
|
Arguments:
|
|
- username (str): User name
|
|
- course_id (obj) : Course key obtained using CourseKey.from_string(course_id_input)
|
|
- mode (CourseMode): course mode
|
|
- enterprise_uuid (str): id to identify the enterprise to enroll under
|
|
- is_active (bool): Optional. A Boolean value that indicates whether the
|
|
enrollment is to be set to inactive (if False). Usually we want a True if enrolling anew.
|
|
|
|
Returns: A serializable dictionary of the new course enrollment. If it hits
|
|
`CourseEnrollmentExistsError` then it logs the error and returns None.
|
|
"""
|
|
user = _validate_enrollment_inputs(username, course_id)
|
|
|
|
with transaction.atomic():
|
|
try:
|
|
response = enrollment_api.add_enrollment(
|
|
username,
|
|
str(course_id),
|
|
mode=mode,
|
|
is_active=is_active,
|
|
enrollment_attributes=None,
|
|
enterprise_uuid=enterprise_uuid,
|
|
)
|
|
log.info('The user [%s] has been enrolled in course run [%s].', username, course_id)
|
|
return response
|
|
except CourseEnrollmentExistsError as error: # pylint: disable=unused-variable
|
|
log.warning('An enrollment already exists for user [%s] in course run [%s].', username, course_id)
|
|
return None
|
|
except CourseEnrollmentError as error:
|
|
log.exception("An error occurred while creating the new course enrollment for user "
|
|
"[%s] in course run [%s]", username, course_id)
|
|
raise error
|
|
finally:
|
|
# Assumes that the ecommerce service uses an API key to authenticate.
|
|
current_enrollment = enrollment_api.get_enrollment(username, str(course_id))
|
|
audit_log(
|
|
'enrollment_change_requested',
|
|
course_id=str(course_id),
|
|
requested_mode=mode,
|
|
actual_mode=current_enrollment['mode'] if current_enrollment else None,
|
|
requested_activation=is_active,
|
|
actual_activation=current_enrollment['is_active'] if current_enrollment else None,
|
|
user_id=user.id
|
|
)
|
|
|
|
|
|
def _validate_enrollment_inputs(username, course_id):
|
|
"""
|
|
Validates username and course_id.
|
|
Raises:
|
|
- UserDoesNotExistException if user not found.
|
|
- CourseIdMissingException if course_id not provided.
|
|
"""
|
|
if not course_id:
|
|
raise CourseIdMissingException("Course ID must be specified to create a new enrollment.")
|
|
if not username:
|
|
raise UserDoesNotExistException('username is a required argument for enrollment')
|
|
try:
|
|
# Lookup the user, instead of using request.user, since request.user may not match the username POSTed.
|
|
user = User.objects.get(username=username)
|
|
except ObjectDoesNotExist as error:
|
|
raise UserDoesNotExistException(f'The user {username} does not exist.') from error
|
|
return user
|