Commit fc17ed26 by Chris Rossi Committed by Diana Huang

Properly handle already emailed courses.

parent 2468c99c
...@@ -3,7 +3,7 @@ Send emails to users inviting them to add their course certificates to their ...@@ -3,7 +3,7 @@ Send emails to users inviting them to add their course certificates to their
LinkedIn profiles. LinkedIn profiles.
""" """
from itertools import imap import json
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from optparse import make_option from optparse import make_option
...@@ -37,16 +37,23 @@ class Command(BaseCommand): ...@@ -37,16 +37,23 @@ class Command(BaseCommand):
def handle(self, *args, **options): def handle(self, *args, **options):
grandfather = options.get('grandfather', False) grandfather = options.get('grandfather', False)
accounts = LinkedIn.objects.filter(has_linkedin_account=True) accounts = LinkedIn.objects.filter(has_linkedin_account=True)
for user in imap(lambda account: account.user, accounts): # lazy for account in accounts:
emailed = json.loads(account.emailed_courses)
user = account.user
certificates = GeneratedCertificate.objects.filter(user=user) certificates = GeneratedCertificate.objects.filter(user=user)
certificates = certificates.filter(status='downloadable') certificates = certificates.filter(status='downloadable')
certificates = [cert for cert in certificates
if cert.course_id not in emailed]
if not certificates: if not certificates:
continue continue
if grandfather: if grandfather:
send_grandfather_email(user, certificates) send_grandfather_email(user, certificates)
emailed.extend([cert.course_id for cert in certificates])
else: else:
for certificate in certificates: for certificate in certificates:
send_email(user, certificate) send_email(user, certificate)
emailed.append(certificate.course_id)
account.emailed_courses = json.dumps(emailed)
def send_grandfather_email(user, certificates): def send_grandfather_email(user, certificates):
......
""" """
Test email scripts. Test email scripts.
""" """
import json
import mock import mock
import unittest import unittest
...@@ -17,11 +18,18 @@ class MailusersTests(unittest.TestCase): ...@@ -17,11 +18,18 @@ class MailusersTests(unittest.TestCase):
@mock.patch('linkedin.management.commands.mailusers.LinkedIn') @mock.patch('linkedin.management.commands.mailusers.LinkedIn')
def test_mail_users(self, linkedin, certificates, send_email): def test_mail_users(self, linkedin, certificates, send_email):
""" """
Test "happy path" for emailing users. Test emailing users.
""" """
fut = mailusers.Command().handle fut = mailusers.Command().handle
fred = mock.Mock(user=mock.Mock(certificates=[1, 2])) cert1 = mock.Mock(course_id=1)
barney = mock.Mock(user=mock.Mock(certificates=[3])) cert2 = mock.Mock(course_id=2)
cert3 = mock.Mock(course_id=3)
fred = mock.Mock(
emailed_courses="[]",
user=mock.Mock(certificates=[cert1, cert2]))
barney = mock.Mock(
emailed_courses="[]",
user=mock.Mock(certificates=[cert3]))
linkedin.objects.filter.return_value = [fred, barney] linkedin.objects.filter.return_value = [fred, barney]
def filter_user(user): def filter_user(user):
...@@ -34,20 +42,29 @@ class MailusersTests(unittest.TestCase): ...@@ -34,20 +42,29 @@ class MailusersTests(unittest.TestCase):
fut() fut()
self.assertEqual( self.assertEqual(
send_email.call_args_list, send_email.call_args_list,
[((fred.user, 1),), [((fred.user, cert1),),
((fred.user, 2),), ((fred.user, cert2),),
((barney.user, 3),)]) ((barney.user, cert3),)])
self.assertEqual(json.loads(fred.emailed_courses), [1, 2])
self.assertEqual(json.loads(barney.emailed_courses), [3])
@mock.patch('linkedin.management.commands.mailusers.send_grandfather_email') @mock.patch('linkedin.management.commands.mailusers.send_grandfather_email')
@mock.patch('linkedin.management.commands.mailusers.GeneratedCertificate') @mock.patch('linkedin.management.commands.mailusers.GeneratedCertificate')
@mock.patch('linkedin.management.commands.mailusers.LinkedIn') @mock.patch('linkedin.management.commands.mailusers.LinkedIn')
def test_mail_users_grandfather(self, linkedin, certificates, send_email): def test_mail_users_grandfather(self, linkedin, certificates, send_email):
""" """
Test "happy path" for sending grandfather emails. Test sending grandfather emails.
""" """
fut = mailusers.Command().handle fut = mailusers.Command().handle
fred = mock.Mock(user=mock.Mock(certificates=[1, 2])) cert1 = mock.Mock(course_id=1)
barney = mock.Mock(user=mock.Mock(certificates=[3])) cert2 = mock.Mock(course_id=2)
cert3 = mock.Mock(course_id=3)
fred = mock.Mock(
emailed_courses="[]",
user=mock.Mock(certificates=[cert1, cert2]))
barney = mock.Mock(
emailed_courses="[]",
user=mock.Mock(certificates=[cert3]))
linkedin.objects.filter.return_value = [fred, barney] linkedin.objects.filter.return_value = [fred, barney]
def filter_user(user): def filter_user(user):
...@@ -60,5 +77,43 @@ class MailusersTests(unittest.TestCase): ...@@ -60,5 +77,43 @@ class MailusersTests(unittest.TestCase):
fut(grandfather=True) fut(grandfather=True)
self.assertEqual( self.assertEqual(
send_email.call_args_list, send_email.call_args_list,
[((fred.user, [1, 2]),), [((fred.user, [cert1, cert2]),),
((barney.user, [3]),)]) ((barney.user, [cert3]),)])
self.assertEqual(json.loads(fred.emailed_courses), [1, 2])
self.assertEqual(json.loads(barney.emailed_courses), [3])
@mock.patch('linkedin.management.commands.mailusers.send_email')
@mock.patch('linkedin.management.commands.mailusers.GeneratedCertificate')
@mock.patch('linkedin.management.commands.mailusers.LinkedIn')
def test_mail_users_only_new_courses(self, linkedin, certificates,
send_email):
"""
Test emailing users, making sure they are only emailed about new
certificates.
"""
fut = mailusers.Command().handle
cert1 = mock.Mock(course_id=1)
cert2 = mock.Mock(course_id=2)
cert3 = mock.Mock(course_id=3)
fred = mock.Mock(
emailed_courses="[1]",
user=mock.Mock(certificates=[cert1, cert2]))
barney = mock.Mock(
emailed_courses="[]",
user=mock.Mock(certificates=[cert3]))
linkedin.objects.filter.return_value = [fred, barney]
def filter_user(user):
"Mock querying the database."
queryset = mock.Mock()
queryset.filter.return_value = user.certificates
return queryset
certificates.objects.filter = filter_user
fut()
self.assertEqual(
send_email.call_args_list,
[((fred.user, cert2),),
((barney.user, cert3),)])
self.assertEqual(json.loads(fred.emailed_courses), [1, 2])
self.assertEqual(json.loads(barney.emailed_courses), [3])
Markdown is supported
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