[MICROBA-676] Changes to the notify_credentials task to filter on username
This commit is contained in:
@@ -155,7 +155,7 @@ def get_certificates_for_user_by_course_keys(user, course_keys):
|
||||
}
|
||||
|
||||
|
||||
def get_recently_modified_certificates(course_keys=None, start_date=None, end_date=None):
|
||||
def get_recently_modified_certificates(course_keys=None, start_date=None, end_date=None, username=None):
|
||||
"""
|
||||
Returns a QuerySet of GeneratedCertificate objects filtered by the input
|
||||
parameters and ordered by modified_date.
|
||||
@@ -171,6 +171,9 @@ def get_recently_modified_certificates(course_keys=None, start_date=None, end_da
|
||||
if end_date:
|
||||
cert_filter_args['modified_date__lte'] = end_date
|
||||
|
||||
if username:
|
||||
cert_filter_args['user__username'] = username
|
||||
|
||||
return GeneratedCertificate.objects.filter(**cert_filter_args).order_by('modified_date')
|
||||
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ def clear_prefetched_course_and_subsection_grades(course_key):
|
||||
_PersistentCourseGrade.clear_prefetched_data(course_key)
|
||||
|
||||
|
||||
def get_recently_modified_grades(course_keys, start_date, end_date):
|
||||
def get_recently_modified_grades(course_keys, start_date, end_date, user=None):
|
||||
"""
|
||||
Returns a QuerySet of PersistentCourseGrade objects filtered by the input
|
||||
parameters and ordered by modified date.
|
||||
@@ -47,6 +47,8 @@ def get_recently_modified_grades(course_keys, start_date, end_date):
|
||||
grade_filter_args['modified__gte'] = start_date
|
||||
if end_date:
|
||||
grade_filter_args['modified__lte'] = end_date
|
||||
if user:
|
||||
grade_filter_args['user_id'] = user.id
|
||||
|
||||
return _PersistentCourseGrade.objects.filter(**grade_filter_args).order_by('modified')
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import time
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
import dateutil.parser
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from opaque_keys import InvalidKeyError
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
@@ -34,6 +34,7 @@ from openedx.core.djangoapps.credentials.signals import handle_cert_change, send
|
||||
from openedx.core.djangoapps.programs.signals import handle_course_cert_changed, handle_course_cert_awarded
|
||||
from openedx.core.djangoapps.site_configuration.models import SiteConfiguration
|
||||
|
||||
User = get_user_model()
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -160,6 +161,11 @@ class Command(BaseCommand):
|
||||
action='store_true',
|
||||
help='Send program award notifications with course notification tasks',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--username',
|
||||
default=None,
|
||||
help='Run the command for a single user',
|
||||
)
|
||||
|
||||
def get_args_from_database(self):
|
||||
""" Returns an options dictionary from the current NotifyCredentialsConfig model. """
|
||||
@@ -183,7 +189,7 @@ class Command(BaseCommand):
|
||||
|
||||
log.info(
|
||||
u"notify_credentials starting, dry-run=%s, site=%s, delay=%d seconds, page_size=%d, "
|
||||
u"from=%s, to=%s, notify_programs=%s, execution=%s",
|
||||
u"from=%s, to=%s, notify_programs=%s, username=%s, execution=%s",
|
||||
options['dry_run'],
|
||||
options['site'],
|
||||
options['delay'],
|
||||
@@ -191,6 +197,7 @@ class Command(BaseCommand):
|
||||
options['start_date'] if options['start_date'] else 'NA',
|
||||
options['end_date'] if options['end_date'] else 'NA',
|
||||
options['notify_programs'],
|
||||
options['username'],
|
||||
'auto' if options['auto'] else 'manual',
|
||||
)
|
||||
|
||||
@@ -200,11 +207,19 @@ class Command(BaseCommand):
|
||||
log.error(u'No site configuration found for site %s', options['site'])
|
||||
|
||||
course_keys = self.get_course_keys(options['courses'])
|
||||
if not (course_keys or options['start_date'] or options['end_date']):
|
||||
raise CommandError('You must specify a filter (e.g. --courses= or --start-date)')
|
||||
if not (course_keys or options['start_date'] or options['end_date'] or options['username']):
|
||||
raise CommandError('You must specify a filter (e.g. --courses= or --start-date or --username)')
|
||||
|
||||
certs = get_recently_modified_certificates(course_keys, options['start_date'], options['end_date'])
|
||||
grades = get_recently_modified_grades(course_keys, options['start_date'], options['end_date'])
|
||||
certs = get_recently_modified_certificates(
|
||||
course_keys, options['start_date'], options['end_date'], options['username']
|
||||
)
|
||||
|
||||
user = None
|
||||
if options['username']:
|
||||
user = User.objects.get(username=options['username'])
|
||||
grades = get_recently_modified_grades(
|
||||
course_keys, options['start_date'], options['end_date'], user
|
||||
)
|
||||
|
||||
log.info('notify_credentials Sending notifications for {certs} certificates and {grades} grades'.format(
|
||||
certs=certs.count(),
|
||||
|
||||
@@ -33,6 +33,7 @@ class TestNotifyCredentials(TestCase):
|
||||
def setUp(self):
|
||||
super(TestNotifyCredentials, self).setUp()
|
||||
self.user = UserFactory.create()
|
||||
self.user2 = UserFactory.create()
|
||||
|
||||
with freeze_time(datetime(2017, 1, 1)):
|
||||
self.cert1 = GeneratedCertificateFactory(user=self.user, course_id='course-v1:edX+Test+1')
|
||||
@@ -42,7 +43,7 @@ class TestNotifyCredentials(TestCase):
|
||||
self.cert3 = GeneratedCertificateFactory(user=self.user, course_id='course-v1:testX+Test+3')
|
||||
with freeze_time(datetime(2017, 2, 1, 5)):
|
||||
self.cert4 = GeneratedCertificateFactory(
|
||||
user=self.user, course_id='course-v1:edX+Test+4', status=CertificateStatuses.downloadable
|
||||
user=self.user2, course_id='course-v1:edX+Test+4', status=CertificateStatuses.downloadable
|
||||
)
|
||||
print(('self.cert1.modified_date', self.cert1.modified_date))
|
||||
|
||||
@@ -57,7 +58,7 @@ class TestNotifyCredentials(TestCase):
|
||||
self.grade3 = PersistentCourseGrade.objects.create(user_id=self.user.id, course_id='course-v1:testX+Test+3',
|
||||
percent_grade=1)
|
||||
with freeze_time(datetime(2017, 2, 1, 5)):
|
||||
self.grade4 = PersistentCourseGrade.objects.create(user_id=self.user.id, course_id='course-v1:edX+Test+4',
|
||||
self.grade4 = PersistentCourseGrade.objects.create(user_id=self.user2.id, course_id='course-v1:edX+Test+4',
|
||||
percent_grade=1)
|
||||
print(('self.grade1.modified', self.grade1.modified))
|
||||
|
||||
@@ -122,6 +123,40 @@ class TestNotifyCredentials(TestCase):
|
||||
self.assertListEqual(list(mock_send.call_args[0][0]), [self.cert2])
|
||||
self.assertListEqual(list(mock_send.call_args[0][1]), [self.grade2])
|
||||
|
||||
@mock.patch(COMMAND_MODULE + '.Command.send_notifications')
|
||||
def test_username_arg(self, mock_send):
|
||||
call_command(
|
||||
Command(), '--start-date', '2017-02-01', '--end-date', '2017-02-02', '--username', self.user2.username
|
||||
)
|
||||
self.assertTrue(mock_send.called)
|
||||
self.assertListEqual(list(mock_send.call_args[0][0]), [self.cert4])
|
||||
self.assertListEqual(list(mock_send.call_args[0][1]), [self.grade4])
|
||||
mock_send.reset_mock()
|
||||
|
||||
call_command(
|
||||
Command(), '--username', self.user2.username
|
||||
)
|
||||
self.assertTrue(mock_send.called)
|
||||
self.assertListEqual(list(mock_send.call_args[0][0]), [self.cert4])
|
||||
self.assertListEqual(list(mock_send.call_args[0][1]), [self.grade4])
|
||||
mock_send.reset_mock()
|
||||
|
||||
call_command(
|
||||
Command(), '--start-date', '2017-02-01', '--end-date', '2017-02-02', '--username', self.user.username
|
||||
)
|
||||
self.assertTrue(mock_send.called)
|
||||
self.assertListEqual(list(mock_send.call_args[0][0]), [self.cert2])
|
||||
self.assertListEqual(list(mock_send.call_args[0][1]), [self.grade2])
|
||||
mock_send.reset_mock()
|
||||
|
||||
call_command(
|
||||
Command(), '--username', self.user2.username
|
||||
)
|
||||
self.assertTrue(mock_send.called)
|
||||
self.assertListEqual(list(mock_send.call_args[0][0]), [self.cert4])
|
||||
self.assertListEqual(list(mock_send.call_args[0][1]), [self.grade4])
|
||||
mock_send.reset_mock()
|
||||
|
||||
@mock.patch(COMMAND_MODULE + '.Command.send_notifications')
|
||||
def test_no_args(self, mock_send):
|
||||
with self.assertRaisesRegex(CommandError, 'You must specify a filter.*'):
|
||||
|
||||
Reference in New Issue
Block a user