Skip to content
Snippets Groups Projects
Unverified Commit 5fa4fcea authored by Christie Rice's avatar Christie Rice Committed by GitHub
Browse files

fix: Handle missing user profile when setting a name in a course certificate (#28319)

MICROBA-1410
parent 9cda17bf
Branches
Tags
No related merge requests found
...@@ -52,7 +52,7 @@ def get_course_enrollment(user, course_run_key): ...@@ -52,7 +52,7 @@ def get_course_enrollment(user, course_run_key):
def get_phone_number(user_id): def get_phone_number(user_id):
""" """
Get a users phone number from the profile, if Get a user's phone number from the profile, if
one exists. Otherwise, return None. one exists. Otherwise, return None.
""" """
try: try:
...@@ -63,6 +63,18 @@ def get_phone_number(user_id): ...@@ -63,6 +63,18 @@ def get_phone_number(user_id):
return student.phone_number or None return student.phone_number or None
def get_name(user_id):
"""
Get a user's name from their profile, if one exists. Otherwise, return None.
"""
try:
student = _UserProfile.objects.get(user_id=user_id)
except _UserProfile.DoesNotExist:
log.exception(f'Could not find UserProfile for id {user_id}')
return None
return student.name or None
def get_course_access_role(user, org, course_id, role): def get_course_access_role(user, org, course_id, role):
""" """
Get a specific CourseAccessRole object. Return None if Get a specific CourseAccessRole object. Return None if
......
...@@ -26,8 +26,10 @@ from common.djangoapps.student.models import ( ...@@ -26,8 +26,10 @@ from common.djangoapps.student.models import (
ManualEnrollmentAudit, ManualEnrollmentAudit,
PendingEmailChange, PendingEmailChange,
PendingNameChange, PendingNameChange,
UserCelebration UserCelebration,
UserProfile
) )
from common.djangoapps.student.models_api import get_name
from common.djangoapps.student.tests.factories import AccountRecoveryFactory, CourseEnrollmentFactory, UserFactory from common.djangoapps.student.tests.factories import AccountRecoveryFactory, CourseEnrollmentFactory, UserFactory
from lms.djangoapps.courseware.models import DynamicUpgradeDeadlineConfiguration from lms.djangoapps.courseware.models import DynamicUpgradeDeadlineConfiguration
from lms.djangoapps.courseware.toggles import ( from lms.djangoapps.courseware.toggles import (
...@@ -728,3 +730,30 @@ class TestUserPostSaveCallback(SharedModuleStoreTestCase): ...@@ -728,3 +730,30 @@ class TestUserPostSaveCallback(SharedModuleStoreTestCase):
course_enrollment.save() course_enrollment.save()
return user return user
class TestProfile(SharedModuleStoreTestCase):
"""
Tests for the user profile
"""
def setUp(self):
super().setUp()
self.user = UserFactory.create()
self.profile = UserProfile.objects.get(user_id=self.user.id)
self.name = self.profile.name
self.course = CourseFactory.create()
def test_name(self):
"""
Test retrieval of the name
"""
assert self.name
name = get_name(self.user.id)
assert name == self.name
def test_name_missing_profile(self):
"""
Test retrieval of the name when the user profile doesn't exist
"""
name = get_name(None)
assert not name
...@@ -10,7 +10,7 @@ These methods should be called from tasks. ...@@ -10,7 +10,7 @@ These methods should be called from tasks.
import logging import logging
from uuid import uuid4 from uuid import uuid4
from common.djangoapps.student.models import UserProfile from common.djangoapps.student import models_api as student_api
from lms.djangoapps.certificates.data import CertificateStatuses from lms.djangoapps.certificates.data import CertificateStatuses
from lms.djangoapps.certificates.models import GeneratedCertificate from lms.djangoapps.certificates.models import GeneratedCertificate
from lms.djangoapps.certificates.utils import emit_certificate_event from lms.djangoapps.certificates.utils import emit_certificate_event
...@@ -66,8 +66,9 @@ def _generate_certificate(user, course_key, status, enrollment_mode, course_grad ...@@ -66,8 +66,9 @@ def _generate_certificate(user, course_key, status, enrollment_mode, course_grad
# Retrieve the existing certificate for the learner if it exists # Retrieve the existing certificate for the learner if it exists
existing_certificate = GeneratedCertificate.certificate_for_student(user, course_key) existing_certificate = GeneratedCertificate.certificate_for_student(user, course_key)
profile = UserProfile.objects.get(user=user) profile_name = student_api.get_name(user.id)
profile_name = profile.name if not profile_name:
profile_name = ''
# Retain the `verify_uuid` from an existing certificate if possible, this will make it possible for the learner to # Retain the `verify_uuid` from an existing certificate if possible, this will make it possible for the learner to
# keep the existing URL to their certificate # keep the existing URL to their certificate
......
...@@ -2,8 +2,10 @@ ...@@ -2,8 +2,10 @@
Tests for certificate generation Tests for certificate generation
""" """
import logging import logging
from unittest import mock
from common.djangoapps.course_modes.models import CourseMode from common.djangoapps.course_modes.models import CourseMode
from common.djangoapps.student.models import UserProfile
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory
from common.djangoapps.util.testing import EventTestMixin from common.djangoapps.util.testing import EventTestMixin
from lms.djangoapps.certificates.data import CertificateStatuses from lms.djangoapps.certificates.data import CertificateStatuses
...@@ -15,6 +17,8 @@ from xmodule.modulestore.tests.factories import CourseFactory ...@@ -15,6 +17,8 @@ from xmodule.modulestore.tests.factories import CourseFactory
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
PROFILE_NAME_METHOD = 'common.djangoapps.student.models_api.get_name'
class CertificateTests(EventTestMixin, ModuleStoreTestCase): class CertificateTests(EventTestMixin, ModuleStoreTestCase):
""" """
...@@ -26,6 +30,8 @@ class CertificateTests(EventTestMixin, ModuleStoreTestCase): ...@@ -26,6 +30,8 @@ class CertificateTests(EventTestMixin, ModuleStoreTestCase):
# Create user, a course run, and an enrollment # Create user, a course run, and an enrollment
self.u = UserFactory() self.u = UserFactory()
self.profile = UserProfile.objects.get(user_id=self.u.id)
self.name = self.profile.name
self.cr = CourseFactory() self.cr = CourseFactory()
self.key = self.cr.id # pylint: disable=no-member self.key = self.cr.id # pylint: disable=no-member
CourseEnrollmentFactory( CourseEnrollmentFactory(
...@@ -65,6 +71,7 @@ class CertificateTests(EventTestMixin, ModuleStoreTestCase): ...@@ -65,6 +71,7 @@ class CertificateTests(EventTestMixin, ModuleStoreTestCase):
assert cert.status == CertificateStatuses.downloadable assert cert.status == CertificateStatuses.downloadable
assert cert.mode == self.enrollment_mode assert cert.mode == self.enrollment_mode
assert cert.grade == self.grade assert cert.grade == self.grade
assert cert.name == self.name
def test_generation_existing_unverified(self): def test_generation_existing_unverified(self):
""" """
...@@ -159,3 +166,24 @@ class CertificateTests(EventTestMixin, ModuleStoreTestCase): ...@@ -159,3 +166,24 @@ class CertificateTests(EventTestMixin, ModuleStoreTestCase):
self.enrollment_mode, self.grade, self.gen_mode) self.enrollment_mode, self.grade, self.gen_mode)
assert generated_cert.status, CertificateStatuses.downloadable assert generated_cert.status, CertificateStatuses.downloadable
assert generated_cert.verify_uuid != '' assert generated_cert.verify_uuid != ''
def test_generation_missing_profile(self):
"""
Test certificate generation when the user profile is missing
"""
GeneratedCertificateFactory(
user=self.u,
course_id=self.key,
mode=CourseMode.AUDIT,
status=CertificateStatuses.unverified
)
with mock.patch(PROFILE_NAME_METHOD, return_value=None):
generate_course_certificate(self.u, self.key, CertificateStatuses.downloadable, self.enrollment_mode,
self.grade, self.gen_mode)
cert = GeneratedCertificate.objects.get(user=self.u, course_id=self.key)
assert cert.status == CertificateStatuses.downloadable
assert cert.mode == self.enrollment_mode
assert cert.grade == self.grade
assert cert.name == ''
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment