From ba7567d0083c2bea4a5748e9e2dce200290b94d2 Mon Sep 17 00:00:00 2001
From: Alie Langston <alangsto@wellesley.edu>
Date: Wed, 9 Oct 2024 09:06:49 -0400
Subject: [PATCH] feat: update management command to manually create verified
 names

---
 .../commands/approve_id_verifications.py      | 34 +++++++++++
 .../tests/test_approve_id_verifications.py    | 59 +++++++++++++++++++
 2 files changed, 93 insertions(+)

diff --git a/lms/djangoapps/verify_student/management/commands/approve_id_verifications.py b/lms/djangoapps/verify_student/management/commands/approve_id_verifications.py
index 3a08ede0aaf6..9f1e43cf600b 100644
--- a/lms/djangoapps/verify_student/management/commands/approve_id_verifications.py
+++ b/lms/djangoapps/verify_student/management/commands/approve_id_verifications.py
@@ -10,9 +10,11 @@
 
 from django.core.management.base import BaseCommand, CommandError
 
+from common.djangoapps.student.models_api import get_name, get_pending_name_change
 from lms.djangoapps.verify_student.api import send_approval_email
 from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification
 from lms.djangoapps.verify_student.utils import earliest_allowed_verification_date
+from openedx.features.name_affirmation_api.utils import get_name_affirmation_service
 
 
 log = logging.getLogger(__name__)
@@ -149,5 +151,37 @@ def _approve_id_verifications(self, user_ids):
         for verification in existing_id_verifications:
             verification.approve(service='idv_verifications command')
             send_approval_email(verification)
+            self._update_verified_name(verification)
 
         return list(failed_user_ids)
+
+    def _update_verified_name(self, verification):
+        """
+        This method manually creates a verified name given a SoftwareSecurePhotoVerification object.
+        """
+
+        name_affirmation_service = get_name_affirmation_service()
+
+        if name_affirmation_service:
+            from edx_name_affirmation.exceptions import VerifiedNameDoesNotExist  # pylint: disable=import-error
+
+            pending_name_change = get_pending_name_change(verification.user)
+            if pending_name_change:
+                full_name = pending_name_change.new_name
+            else:
+                full_name = get_name(verification.user.id)
+
+            try:
+                name_affirmation_service.update_verified_name_status(
+                    verification.user,
+                    'approved',
+                    verification_attempt_id=verification.id
+                )
+            except VerifiedNameDoesNotExist:
+                name_affirmation_service.create_verified_name(
+                    verification.user,
+                    verification.name,
+                    full_name,
+                    verification_attempt_id=verification.id,
+                    status='approved',
+                )
diff --git a/lms/djangoapps/verify_student/management/commands/tests/test_approve_id_verifications.py b/lms/djangoapps/verify_student/management/commands/tests/test_approve_id_verifications.py
index e6e580c1d1a6..6eccee194795 100644
--- a/lms/djangoapps/verify_student/management/commands/tests/test_approve_id_verifications.py
+++ b/lms/djangoapps/verify_student/management/commands/tests/test_approve_id_verifications.py
@@ -6,6 +6,8 @@
 import logging
 import os
 import tempfile
+from unittest import skipUnless
+from unittest.mock import MagicMock, patch
 
 import pytest
 from django.core import mail
@@ -15,9 +17,12 @@
 
 from common.djangoapps.student.tests.factories import UserFactory, UserProfileFactory
 from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification
+from openedx.features.name_affirmation_api.utils import get_name_affirmation_service
 
 LOGGER_NAME = 'lms.djangoapps.verify_student.management.commands.approve_id_verifications'
 
+name_affirmation_service = get_name_affirmation_service()
+
 
 @ddt.ddt
 class TestApproveIDVerificationsCommand(TestCase):
@@ -158,3 +163,57 @@ def test_invalid_file_path(self):
         """
         with pytest.raises(CommandError):
             call_command('approve_id_verifications', 'invalid/user_id/file/path')
+
+    @skipUnless(name_affirmation_service is not None, 'Requires Name Affirmation')
+    @patch('lms.djangoapps.verify_student.management.commands.approve_id_verifications.get_name_affirmation_service')
+    def test_create_verified_names(self, mock_get_service):
+        mock_service = MagicMock()
+        mock_get_service.return_value = mock_service
+
+        verification = SoftwareSecurePhotoVerification.objects.create(
+            user=self.user1_profile.user,
+            name=self.user1_profile.name,
+            status='submitted',
+        )
+
+        call_command('approve_id_verifications', self.tmp_file_path)
+        mock_service.update_verified_name_status.assert_called_with(
+            self.user1_profile.user,
+            'approved',
+            verification_attempt_id=verification.id,
+        )
+
+    @skipUnless(name_affirmation_service is not None, 'Requires Name Affirmation')
+    @patch('lms.djangoapps.verify_student.management.commands.approve_id_verifications.get_name')
+    @patch('lms.djangoapps.verify_student.management.commands.approve_id_verifications.get_pending_name_change')
+    @patch('lms.djangoapps.verify_student.management.commands.approve_id_verifications.get_name_affirmation_service')
+    @ddt.data(
+        '',
+        MagicMock(new_name='test')
+    )
+    def test_create_update_verified_names(self, pending_name, mock_get_service, mock_get_pending, mock_get_name):
+        from edx_name_affirmation.exceptions import VerifiedNameDoesNotExist  # pylint: disable=import-error
+
+        mock_service = MagicMock()
+        mock_get_service.return_value = mock_service
+        mock_service.update_verified_name_status.side_effect = VerifiedNameDoesNotExist()
+
+        mock_get_pending.return_value = pending_name
+        mock_get_name.return_value = self.user1_profile.name
+
+        verification = SoftwareSecurePhotoVerification.objects.create(
+            user=self.user1_profile.user,
+            name=self.user1_profile.name,
+            status='submitted',
+        )
+
+        expected_name = 'test' if pending_name else self.user1_profile.name
+
+        call_command('approve_id_verifications', self.tmp_file_path)
+        mock_service.create_verified_name.assert_called_with(
+            verification.user,
+            verification.name,
+            expected_name,
+            verification_attempt_id=verification.id,
+            status='approved',
+        )