Skip to content

Commit

Permalink
feat: use username for course completion API instead of lms_user_id (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
aht007 authored Jul 17, 2023
1 parent 3b1ff5c commit 06923c7
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1392,4 +1392,4 @@ def test_course_completion_exception_triggers_task(self, mock_get_courses_comple
assert response.status_code == 204
mock_task.assert_called_once_with(args=([str(course_entitlement.uuid)],
[str(enrollment.course_id)],
self.user.id))
self.user.username))
24 changes: 14 additions & 10 deletions common/djangoapps/entitlements/rest_api/v1/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import logging

from django.contrib.auth import get_user_model
from django.db import IntegrityError, transaction
from django.db.models import Q
from django.http import HttpResponseBadRequest
Expand Down Expand Up @@ -42,6 +43,7 @@
from openedx.core.djangoapps.credentials.utils import get_courses_completion_status
from openedx.core.djangoapps.user_api.preferences.api import update_email_opt_in

User = get_user_model()
log = logging.getLogger(__name__)


Expand Down Expand Up @@ -552,36 +554,38 @@ def _process_revoke_and_downgrade_to_audit(self, course_entitlements, user_id, r
course completion status.
"""
entitled_course_ids = []
user = User.objects.get(id=user_id)
username = user.username
for course_entitlement in course_entitlements:
if course_entitlement.enrollment_course_run is not None:
entitled_course_ids.append(str(course_entitlement.enrollment_course_run.course_id))

log.info('B2C_SUBSCRIPTIONS: Getting course completion status for user %s and entitled_course_ids %s',
user_id,
log.info('B2C_SUBSCRIPTIONS: Getting course completion status for user [%s] and entitled_course_ids %s',
username,
entitled_course_ids)
awarded_cert_course_ids, is_exception = get_courses_completion_status(user_id, entitled_course_ids)
awarded_cert_course_ids, is_exception = get_courses_completion_status(username, entitled_course_ids)

log.info('B2C_SUBSCRIPTIONS: Got course completion response %s for user %s and entitled_course_ids %s',
log.info('B2C_SUBSCRIPTIONS: Got course completion response %s for user [%s] and entitled_course_ids %s',
awarded_cert_course_ids,
user_id,
username,
entitled_course_ids)

if is_exception:
# Trigger the retry task asynchronously
log.exception('B2C_SUBSCRIPTIONS: Exception occurred while getting course completion status for user %s '
'and entitled_course_ids %s',
user_id,
username,
entitled_course_ids)
retry_revoke_subscriptions_verified_access.apply_async(args=(revocable_entitlement_uuids,
entitled_course_ids,
user_id))
username))
return
log.info('B2C_SUBSCRIPTIONS: Starting revoke_entitlements_and_downgrade_courses_to_audit for user %s and '
log.info('B2C_SUBSCRIPTIONS: Starting revoke_entitlements_and_downgrade_courses_to_audit for user [%s] and '
'awarded_cert_course_ids %s and revocable_entitlement_uuids %s',
user_id,
username,
awarded_cert_course_ids,
revocable_entitlement_uuids)
revoke_entitlements_and_downgrade_courses_to_audit(course_entitlements, user_id, awarded_cert_course_ids,
revoke_entitlements_and_downgrade_courses_to_audit(course_entitlements, username, awarded_cert_course_ids,
revocable_entitlement_uuids)

def post(self, request):
Expand Down
18 changes: 9 additions & 9 deletions common/djangoapps/entitlements/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,36 +157,36 @@ def expire_and_create_entitlements(self, entitlement_ids, support_username):


@shared_task(bind=True)
def retry_revoke_subscriptions_verified_access(self, revocable_entitlement_uuids, entitled_course_ids, user_id):
def retry_revoke_subscriptions_verified_access(self, revocable_entitlement_uuids, entitled_course_ids, username):
"""
Task to process course access revoke and move to audit.
This is called only if call to get_courses_completion_status fails due to any exception.
"""
course_entitlements = CourseEntitlement.objects.filter(uuid__in=revocable_entitlement_uuids)
course_entitlements = course_entitlements.select_related('user').select_related('enrollment_course_run')
if course_entitlements.exists():
awarded_cert_course_ids, is_exception = get_courses_completion_status(user_id, entitled_course_ids)
awarded_cert_course_ids, is_exception = get_courses_completion_status(username, entitled_course_ids)
if is_exception:
try:
countdown = 2 ** self.request.retries
self.retry(countdown=countdown, max_retries=3)
except MaxRetriesExceededError:
log.exception(
'B2C_SUBSCRIPTIONS: Failed to process retry_revoke_subscriptions_verified_access '
'for user_id %s and entitlement_uuids %s',
user_id,
'for user [%s] and entitlement_uuids %s',
username,
revocable_entitlement_uuids
)
return
log.info('B2C_SUBSCRIPTIONS: Starting revoke_entitlements_and_downgrade_courses_to_audit for user %s and '
log.info('B2C_SUBSCRIPTIONS: Starting revoke_entitlements_and_downgrade_courses_to_audit for user [%s] and '
'awarded_cert_course_ids %s and revocable_entitlement_uuids %s from retry task',
user_id,
username,
awarded_cert_course_ids,
revocable_entitlement_uuids)
revoke_entitlements_and_downgrade_courses_to_audit(course_entitlements, user_id, awarded_cert_course_ids,
revoke_entitlements_and_downgrade_courses_to_audit(course_entitlements, username, awarded_cert_course_ids,
revocable_entitlement_uuids)
else:
log.info('B2C_SUBSCRIPTIONS: Entitlements not found for the provided entitlements uuids %s '
'for user_id %s duing the retry_revoke_subscriptions_verified_access task',
'for user [%s] duing the retry_revoke_subscriptions_verified_access task',
revocable_entitlement_uuids,
user_id)
username)
14 changes: 7 additions & 7 deletions common/djangoapps/entitlements/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,16 @@ def is_course_run_entitlement_fulfillable(
return course_overview.start and can_upgrade and (is_enrolled or can_enroll)


def revoke_entitlements_and_downgrade_courses_to_audit(course_entitlements, user_id, awarded_cert_course_ids,
def revoke_entitlements_and_downgrade_courses_to_audit(course_entitlements, username, awarded_cert_course_ids,
revocable_entitlement_uuids):
"""
This method expires the entitlements for provided course_entitlements and also moves the enrollments
to audit for the course entitlements which have not been completed yet(not a part of the provided exclusion_list).
"""

log.info('B2C_SUBSCRIPTIONS: Starting revoke_entitlements_and_downgrade_courses_to_audit for '
'user: %s, course_entitlements_uuids: %s, awarded_cert_course_ids: %s',
user_id,
'user: [%s], course_entitlements_uuids: %s, awarded_cert_course_ids: %s',
username,
revocable_entitlement_uuids,
awarded_cert_course_ids)
for course_entitlement in course_entitlements:
Expand All @@ -87,11 +87,11 @@ def revoke_entitlements_and_downgrade_courses_to_audit(course_entitlements, user
course_entitlement.expire_entitlement()
update_enrollment(username, str(course_id), CourseMode.AUDIT, include_expired=True)
else:
log.warning('B2C_SUBSCRIPTIONS: Enrollment mode mismatch for user_id: %s and course_id: %s',
user_id,
log.warning('B2C_SUBSCRIPTIONS: Enrollment mode mismatch for user: %s and course_id: %s',
username,
course_id)
log.info('B2C_SUBSCRIPTIONS: Completed revoke_entitlements_and_downgrade_courses_to_audit for '
'user: %s, course_entitlements_uuids: %s, awarded_cert_course_ids: %s',
user_id,
'user: [%s], course_entitlements_uuids: %s, awarded_cert_course_ids: %s',
username,
revocable_entitlement_uuids,
awarded_cert_course_ids)
20 changes: 10 additions & 10 deletions openedx/core/djangoapps/credentials/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,11 @@ def get_credentials(user, program_uuid=None, credential_type=None):
)


def get_courses_completion_status(lms_user_id, course_run_ids):
def get_courses_completion_status(username, course_run_ids):
"""
Given the lms_user_id and course run ids, checks for course completion status
Given the username and course run ids, checks for course completion status
Arguments:
lms_user_id (User): The user to authenticate as when requesting credentials.
username (User): Username of the user whose credentials are being requested.
course_run_ids(List): list of course run ids for which we need to check the completion status
Returns:
list of course_run_ids for which user has completed the course
Expand All @@ -134,33 +134,33 @@ def get_courses_completion_status(lms_user_id, course_run_ids):
api_response = api_client.post(
completion_status_url,
json={
'lms_user_id': lms_user_id,
'username': username,
'course_runs': course_run_ids,
}
)
api_response.raise_for_status()
course_completion_response = api_response.json()
except Exception as exc: # pylint: disable=broad-except
log.exception("An unexpected error occurred while reqeusting course completion statuses "
"for lms_user_id [%s] for course_run_ids [%s] with exc [%s]:",
lms_user_id,
"for user [%s] for course_run_ids [%s] with exc [%s]:",
username,
course_run_ids,
exc
)
return [], True
# Yes, This is course_credentials_data. The key is named status but
# it contains all the courses data from credentials.
log.info("Course completion status response for lms_user_id [%s] for course_run_ids [%s] is [%s]",
lms_user_id,
log.info("Course completion status response for user [%s] for course_run_ids [%s] is [%s]",
username,
course_run_ids,
course_completion_response)
course_credentials_data = course_completion_response.get('status', [])
if course_credentials_data is not None:
filtered_records = [course_data['course_run']['key'] for course_data in course_credentials_data if
course_data['course_run']['key'] in course_run_ids and
course_data['status'] == settings.CREDENTIALS_COURSE_COMPLETION_STATE]
log.info("Filtered course completion status response for lms_user_id [%s] for course_run_ids [%s] is [%s]",
lms_user_id,
log.info("Filtered course completion status response for user [%s] for course_run_ids [%s] is [%s]",
username,
course_run_ids,
filtered_records)
return filtered_records, False
Expand Down

0 comments on commit 06923c7

Please sign in to comment.