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.
This commit is contained in:
@@ -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,8 +73,9 @@ class Command(BaseCommand):
|
||||
if not certificates:
|
||||
continue
|
||||
if grandfather:
|
||||
self.send_grandfather_email(user, certificates)
|
||||
emailed.extend([cert.course_id for cert in 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:
|
||||
self.send_triggered_email(user, certificate)
|
||||
@@ -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,13 +133,14 @@ 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'
|
||||
self.send_email(user, subject, body)
|
||||
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()
|
||||
|
||||
@@ -115,8 +115,24 @@ class MailusersTests(TestCase):
|
||||
self.assertEqual(len(mail.outbox), 2)
|
||||
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):
|
||||
"""
|
||||
|
||||
70
lms/djangoapps/linkedin/migrations/0001_initial.py
Normal file
70
lms/djangoapps/linkedin/migrations/0001_initial.py
Normal file
@@ -0,0 +1,70 @@
|
||||
# -*- 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']
|
||||
0
lms/djangoapps/linkedin/migrations/__init__.py
Normal file
0
lms/djangoapps/linkedin/migrations/__init__.py
Normal file
@@ -1147,10 +1147,6 @@ GRADES_DOWNLOAD = {
|
||||
##################### LinkedIn #####################
|
||||
INSTALLED_APPS += ('django_openid_auth',)
|
||||
|
||||
LINKEDIN_API = {
|
||||
'COMPANY_NAME': 'edX',
|
||||
|
||||
}
|
||||
|
||||
############################ LinkedIn Integration #############################
|
||||
INSTALLED_APPS += ('linkedin',)
|
||||
|
||||
Reference in New Issue
Block a user