Skip to content

Commit

Permalink
Merge pull request openedx#34875 from openedx/michaelroytman/COSMO-31…
Browse files Browse the repository at this point in the history
…0-idv-approval-email-in-command

Send IDV approval email in approve_id_verifications management command
  • Loading branch information
MichaelRoytman authored May 31, 2024
2 parents f12cd32 + f94a7f7 commit 8677558
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 21 deletions.
35 changes: 35 additions & 0 deletions lms/djangoapps/verify_student/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""
API module.
"""
from django.conf import settings
from django.utils.translation import gettext as _

from lms.djangoapps.verify_student.emails import send_verification_approved_email
from lms.djangoapps.verify_student.tasks import send_verification_status_email


def send_approval_email(attempt):
"""
Send an approval email to the learner associated with the IDV attempt.
"""
verification_status_email_vars = {
'platform_name': settings.PLATFORM_NAME,
}

expiration_datetime = attempt.expiration_datetime.date()
if settings.VERIFY_STUDENT.get('USE_DJANGO_MAIL'):
verification_status_email_vars['expiration_datetime'] = expiration_datetime.strftime("%m/%d/%Y")
verification_status_email_vars['full_name'] = attempt.user.profile.name
subject = _("Your {platform_name} ID verification was approved!").format(
platform_name=settings.PLATFORM_NAME
)
context = {
'subject': subject,
'template': 'emails/passed_verification_email.txt',
'email': attempt.user.email,
'email_vars': verification_status_email_vars
}
send_verification_status_email.delay(context)
else:
email_context = {'user': attempt.user, 'expiration_datetime': expiration_datetime.strftime("%m/%d/%Y")}
send_verification_approved_email(context=email_context)
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
from django.core.management.base import BaseCommand, CommandError

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

Expand Down Expand Up @@ -125,8 +126,8 @@ def _approve_verifications_from_file(self, user_ids_file, batch_size, sleep_time

def _approve_id_verifications(self, user_ids):
"""
This command manually approves ID verification attempts for a provided set of learners whose ID verification
attempt is in the submitted or must_retry state.
This method manually approves ID verification attempts for a provided set of user IDs so long as the attempt
is in the submitted or must_retry state. This method also send an IDV approval email to the user.
Arguments:
user_ids (list): user IDs of the users whose ID verification attempt should be manually approved
Expand All @@ -148,5 +149,6 @@ def _approve_id_verifications(self, user_ids):

for verification in existing_id_verifications:
verification.approve(service='idv_verifications command')
send_approval_email(verification)

return list(failed_user_ids)
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import tempfile

import pytest
from django.core import mail
from django.core.management import CommandError, call_command
from django.test import TestCase
from testfixtures import LogCapture
Expand Down Expand Up @@ -70,6 +71,35 @@ def test_approve_id_verifications(self, status):

assert SoftwareSecurePhotoVerification.objects.filter(status='approved').count() == 3

@ddt.data('submitted', 'must_retry')
def test_approve_id_verifications_email(self, status):
"""
Tests that the approve_id_verifications management command correctly sends approval emails.
"""
# Create SoftwareSecurePhotoVerification instances for the users.
for user in [self.user1_profile, self.user2_profile]:
SoftwareSecurePhotoVerification.objects.create(
user=user.user,
name=user.name,
status=status,
)
SoftwareSecurePhotoVerification.objects.create(
user=self.user3_profile.user,
name=self.user3_profile.name,
status='denied',
)

call_command('approve_id_verifications', self.tmp_file_path)

assert len(mail.outbox) == 2

# All three emails should have equal expiration dates, so just pick one from an attempt.
expiration_date = SoftwareSecurePhotoVerification.objects.first().expiration_datetime
for email in mail.outbox:
assert email.subject == 'Your édX ID verification was approved!'
assert 'Your édX ID verification photos have been approved' in email.body
assert expiration_date.strftime("%m/%d/%Y") in email.body

def test_user_does_not_exist_log(self):
"""
Tests that the approve_id_verifications management command logs an error when an invalid user ID is
Expand Down
43 changes: 43 additions & 0 deletions lms/djangoapps/verify_student/tests/test_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""
Tests of API module.
"""
from unittest.mock import patch

import ddt
from django.conf import settings
from django.core import mail
from django.test import TestCase

from common.djangoapps.student.tests.factories import UserFactory
from lms.djangoapps.verify_student.api import send_approval_email
from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification


@ddt.ddt
class TestSendApprovalEmail(TestCase):
"""
Test cases for the send_approval_email API method.
"""
def setUp(self):
super().setUp()

self.user = UserFactory.create()
self.attempt = SoftwareSecurePhotoVerification(
status="submitted",
user=self.user
)
self.attempt.save()

def _assert_verification_approved_email(self, expiration_date):
"""Check that a verification approved email was sent."""
assert len(mail.outbox) == 1
email = mail.outbox[0]
assert email.subject == 'Your édX ID verification was approved!'
assert 'Your édX ID verification photos have been approved' in email.body
assert expiration_date.strftime("%m/%d/%Y") in email.body

@ddt.data(True, False)
def test_send_approval(self, use_ace):
with patch.dict(settings.VERIFY_STUDENT, {'USE_DJANGO_MAIL': use_ace}):
send_approval_email(self.attempt)
self._assert_verification_approved_email(self.attempt.expiration_datetime)
22 changes: 3 additions & 19 deletions lms/djangoapps/verify_student/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
from common.djangoapps.util.json_request import JsonResponse
from common.djangoapps.util.views import require_global_staff
from lms.djangoapps.commerce.utils import EcommerceService, is_account_activation_requirement_disabled
from lms.djangoapps.verify_student.emails import send_verification_approved_email, send_verification_confirmation_email
from lms.djangoapps.verify_student.api import send_approval_email
from lms.djangoapps.verify_student.emails import send_verification_confirmation_email
from lms.djangoapps.verify_student.image import InvalidImageData, decode_image_data
from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification, VerificationDeadline
from lms.djangoapps.verify_student.tasks import send_verification_status_email
Expand Down Expand Up @@ -1117,24 +1118,7 @@ def results_callback(request): # lint-amnesty, pylint: disable=too-many-stateme
log.info("[COSMO-184] Approved verification for receipt_id={receipt_id}.".format(receipt_id=receipt_id))
attempt.approve()

expiration_datetime = attempt.expiration_datetime.date()
if settings.VERIFY_STUDENT.get('USE_DJANGO_MAIL'):
verification_status_email_vars['expiration_datetime'] = expiration_datetime.strftime("%m/%d/%Y")
verification_status_email_vars['full_name'] = user.profile.name
subject = _("Your {platform_name} ID verification was approved!").format(
platform_name=settings.PLATFORM_NAME
)
context = {
'subject': subject,
'template': 'emails/passed_verification_email.txt',
'email': user.email,
'email_vars': verification_status_email_vars
}
send_verification_status_email.delay(context)
else:
email_context = {'user': user, 'expiration_datetime': expiration_datetime.strftime("%m/%d/%Y")}
send_verification_approved_email(context=email_context)

send_approval_email(attempt)
elif result == "FAIL":
log.debug("Denying verification for %s", receipt_id)

Expand Down

0 comments on commit 8677558

Please sign in to comment.