Commit fdf531ae by Diana Huang

Migrations for LinkedIn.

Clean up common.

Add the ability to dry-run the command without sending e-mail.

Don't save courses sent during a dry run

Switch to EmailMessage for LinkedIn so we can send HTML emails

Update subject copy.

Use correct name for CertificationName

Fix up certificate url information.
parent 469fab58
......@@ -7,7 +7,7 @@ import json
import urllib
from django.conf import settings
from django.core.mail import send_mail
from django.core.mail import EmailMessage
from django.core.management.base import BaseCommand
from django.template import Context
from django.template.loader import get_template
......@@ -43,6 +43,13 @@ class Command(BaseCommand):
"all users that have earned certificates to date to add their "
"certificates. Afterwards the default, one email per "
"certificate mail form will be used."),)
option_list = option_list + (
make_option(
'--mock',
action='store_true',
dest='mock_run',
default=False,
help="Run without sending the final e-mails."),)
def __init__(self):
super(Command, self).__init__()
......@@ -50,6 +57,7 @@ class Command(BaseCommand):
def handle(self, *args, **options):
whitelist = settings.LINKEDIN_API['EMAIL_WHITELIST']
grandfather = options.get('grandfather', False)
mock_run = options.get('mock_run', False)
accounts = LinkedIn.objects.filter(has_linkedin_account=True)
for account in accounts:
user = account.user
......@@ -65,7 +73,8 @@ class Command(BaseCommand):
if not certificates:
continue
if grandfather:
self.send_grandfather_email(user, certificates)
self.send_grandfather_email(user, certificates, mock_run)
if not mock_run:
emailed.extend([cert.course_id for cert in certificates])
else:
for certificate in certificates:
......@@ -83,11 +92,11 @@ class Command(BaseCommand):
tracking_code = '-'.join([
'eml',
'prof', # the 'product'--no idea what that's supposed to mean
course.org, # Partner's name
'edX', # Partner's name
course.number, # Certificate's name
'gf' if grandfather else 'T'])
query = [
('pfCertificationName', certificate.name),
('pfCertificationName', course.display_name_with_default),
('pfAuthorityName', settings.PLATFORM_NAME),
('pfAuthorityId', settings.LINKEDIN_API['COMPANY_ID']),
('pfCertificationUrl', certificate.download_url),
......@@ -99,7 +108,7 @@ class Command(BaseCommand):
('force', 'true')]
return 'http://www.linkedin.com/profile/guided?' + urllib.urlencode(query)
def send_grandfather_email(self, user, certificates):
def send_grandfather_email(self, user, certificates, mock_run=False):
"""
Send the 'grandfathered' email informing historical students that they
may now post their certificates on their LinkedIn profiles.
......@@ -124,12 +133,13 @@ class Command(BaseCommand):
'course_title': course_title,
'course_image_url': course_img_url,
'course_end_date': course_end_date,
'linkedin_add_url': self.certificate_url(cert),
'linkedin_add_url': self.certificate_url(cert, True),
})
context = {'courses_list': courses_list, 'num_courses': len(courses_list)}
body = render_to_string('linkedin/linkedin_email.html', context)
subject = 'Congratulations! Put your certificates on LinkedIn'
subject = '{}, Add your Achievements to your LinkedIn Profile'.format(user.profile.name)
if not mock_run:
self.send_email(user, subject, body)
def send_triggered_email(self, user, certificate):
......@@ -153,4 +163,6 @@ class Command(BaseCommand):
"""
fromaddr = settings.DEFAULT_FROM_EMAIL
toaddr = '%s <%s>' % (user.profile.name, user.email)
send_mail(subject, body, fromaddr, (toaddr,))
msg = EmailMessage(subject, body, fromaddr, (toaddr,))
msg.content_subtype = "html"
msg.send()
......@@ -116,7 +116,23 @@ class MailusersTests(TestCase):
self.assertEqual(
mail.outbox[0].to, ['Fred Flintstone <fred@bedrock.gov>'])
self.assertEqual(
mail.outbox[0].subject, 'Fred Flintstone, Add your Achievements to your LinkedIn Profile')
self.assertEqual(
mail.outbox[1].to, ['Barney Rubble <barney@bedrock.gov>'])
self.assertEqual(
mail.outbox[1].subject, 'Barney Rubble, Add your Achievements to your LinkedIn Profile')
def test_mail_users_grandfather_mock(self):
"""
test that we aren't sending anything when in mock_run mode
"""
fut = mailusers.Command().handle
fut(grandfather=True, mock_run=True)
self.assertEqual(
json.loads(self.fred.linkedin.emailed_courses), [])
self.assertEqual(
json.loads(self.barney.linkedin.emailed_courses), [])
self.assertEqual(len(mail.outbox), 0)
def test_mail_users_only_new_courses(self):
"""
......
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'LinkedIn'
db.create_table('linkedin_linkedin', (
('user', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['auth.User'], unique=True, primary_key=True)),
('has_linkedin_account', self.gf('django.db.models.fields.NullBooleanField')(default=None, null=True, blank=True)),
('emailed_courses', self.gf('django.db.models.fields.TextField')(default='[]')),
))
db.send_create_signal('linkedin', ['LinkedIn'])
def backwards(self, orm):
# Deleting model 'LinkedIn'
db.delete_table('linkedin_linkedin')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'linkedin.linkedin': {
'Meta': {'object_name': 'LinkedIn'},
'emailed_courses': ('django.db.models.fields.TextField', [], {'default': "'[]'"}),
'has_linkedin_account': ('django.db.models.fields.NullBooleanField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'})
}
}
complete_apps = ['linkedin']
\ No newline at end of file
......@@ -1147,10 +1147,6 @@ GRADES_DOWNLOAD = {
##################### LinkedIn #####################
INSTALLED_APPS += ('django_openid_auth',)
LINKEDIN_API = {
'COMPANY_NAME': 'edX',
}
############################ LinkedIn Integration #############################
INSTALLED_APPS += ('linkedin',)
......
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