Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
f780b02b
Commit
f780b02b
authored
Aug 03, 2017
by
Waheed Ahmed
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Send welcome email to inactive learners on registration.
LEARNER-2039
parent
941605cc
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
91 additions
and
30 deletions
+91
-30
lms/djangoapps/email_marketing/migrations/0007_auto_20170809_0653.py
+29
-0
lms/djangoapps/email_marketing/migrations/0008_auto_20170809_0539.py
+27
-0
lms/djangoapps/email_marketing/models.py
+12
-4
lms/djangoapps/email_marketing/signals.py
+2
-2
lms/djangoapps/email_marketing/tasks.py
+4
-5
lms/djangoapps/email_marketing/tests/test_signals.py
+17
-19
No files found.
lms/djangoapps/email_marketing/migrations/0007_auto_20170809_0653.py
0 → 100644
View file @
f780b02b
# -*- coding: utf-8 -*-
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'email_marketing'
,
'0006_auto_20170711_0615'
),
]
operations
=
[
migrations
.
AddField
(
model_name
=
'emailmarketingconfiguration'
,
name
=
'sailthru_welcome_template'
,
field
=
models
.
CharField
(
help_text
=
'Sailthru template to use on welcome send.'
,
max_length
=
20
,
blank
=
True
),
),
migrations
.
AlterField
(
model_name
=
'emailmarketingconfiguration'
,
name
=
'sailthru_activation_template'
,
field
=
models
.
CharField
(
help_text
=
'DEPRECATED: use sailthru_welcome_template instead.'
,
max_length
=
20
,
blank
=
True
),
),
migrations
.
AlterField
(
model_name
=
'emailmarketingconfiguration'
,
name
=
'welcome_email_send_delay'
,
field
=
models
.
IntegerField
(
default
=
600
,
help_text
=
'Number of seconds to delay the sending of User Welcome email after user has been created'
),
),
]
lms/djangoapps/email_marketing/migrations/0008_auto_20170809_0539.py
0 → 100644
View file @
f780b02b
# -*- coding: utf-8 -*-
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
def
migrate_data_forwards
(
apps
,
schema_editor
):
EmailMarketingConfiguration
=
apps
.
get_model
(
'email_marketing'
,
'EmailMarketingConfiguration'
)
EmailMarketingConfiguration
.
objects
.
all
()
.
update
(
sailthru_welcome_template
=
models
.
F
(
'sailthru_activation_template'
)
)
def
migrate_data_backwards
(
apps
,
schema_editor
):
# Just copying old field's value to new one in forward migration, so nothing needed here.
pass
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'email_marketing'
,
'0007_auto_20170809_0653'
),
]
operations
=
[
migrations
.
RunPython
(
migrate_data_forwards
,
migrate_data_backwards
)
]
lms/djangoapps/email_marketing/models.py
View file @
f780b02b
...
...
@@ -51,7 +51,15 @@ class EmailMarketingConfiguration(ConfigurationModel):
max_length
=
20
,
blank
=
True
,
help_text
=
_
(
"Sailthru template to use on activation send. "
"DEPRECATED: use sailthru_welcome_template instead."
)
)
sailthru_welcome_template
=
models
.
fields
.
CharField
(
max_length
=
20
,
blank
=
True
,
help_text
=
_
(
"Sailthru template to use on welcome send."
)
)
...
...
@@ -132,7 +140,7 @@ class EmailMarketingConfiguration(ConfigurationModel):
welcome_email_send_delay
=
models
.
fields
.
IntegerField
(
default
=
600
,
help_text
=
_
(
"Number of seconds to delay the sending of User Welcome email after user has been
activ
ated"
"Number of seconds to delay the sending of User Welcome email after user has been
cre
ated"
)
)
...
...
@@ -145,5 +153,5 @@ class EmailMarketingConfiguration(ConfigurationModel):
)
def
__unicode__
(
self
):
return
u"Email marketing configuration: New user list
%
s,
Activation
template:
%
s"
%
\
(
self
.
sailthru_new_user_list
,
self
.
sailthru_
activation
_template
)
return
u"Email marketing configuration: New user list
%
s,
Welcome
template:
%
s"
%
\
(
self
.
sailthru_new_user_list
,
self
.
sailthru_
welcome
_template
)
lms/djangoapps/email_marketing/signals.py
View file @
f780b02b
...
...
@@ -149,9 +149,9 @@ def email_marketing_user_field_changed(sender, user=None, table=None, setting=No
if
not
email_config
.
enabled
:
return
# perform update asynchronously
, flag if activation
# perform update asynchronously
update_user
.
delay
(
_create_sailthru_user_vars
(
user
,
user
.
profile
),
user
.
email
,
site
=
_get_current_site
(),
new_user
=
False
,
activation
=
(
setting
==
'is_active'
)
and
new_value
is
True
)
new_user
=
False
)
elif
setting
==
'email'
:
# email update is special case
...
...
lms/djangoapps/email_marketing/tasks.py
View file @
f780b02b
...
...
@@ -59,14 +59,13 @@ def get_email_cookies_via_sailthru(self, user_email, post_parms):
# pylint: disable=not-callable
@task
(
bind
=
True
,
default_retry_delay
=
3600
,
max_retries
=
24
)
def
update_user
(
self
,
sailthru_vars
,
email
,
site
=
None
,
new_user
=
False
,
activation
=
False
):
def
update_user
(
self
,
sailthru_vars
,
email
,
site
=
None
,
new_user
=
False
):
"""
Adds/updates Sailthru profile information for a user.
Args:
sailthru_vars(dict): User profile information to pass as 'vars' to Sailthru
email(str): User email address
new_user(boolean): True if new registration
activation(boolean): True if activation request
Returns:
None
"""
...
...
@@ -95,15 +94,15 @@ def update_user(self, sailthru_vars, email, site=None, new_user=False, activatio
max_retries
=
email_config
.
sailthru_max_retries
)
return
# if
activating
user, send welcome email
if
activation
and
email_config
.
sailthru_activation
_template
:
# if
new
user, send welcome email
if
new_user
and
email_config
.
sailthru_welcome
_template
:
scheduled_datetime
=
datetime
.
utcnow
()
+
timedelta
(
seconds
=
email_config
.
welcome_email_send_delay
)
try
:
sailthru_response
=
sailthru_client
.
api_post
(
"send"
,
{
"email"
:
email
,
"template"
:
email_config
.
sailthru_
activation
_template
,
"template"
:
email_config
.
sailthru_
welcome
_template
,
"schedule_time"
:
scheduled_datetime
.
strftime
(
'
%
Y-
%
m-
%
dT
%
H:
%
M:
%
SZ'
)
}
)
...
...
lms/djangoapps/email_marketing/tests/test_signals.py
View file @
f780b02b
...
...
@@ -41,7 +41,7 @@ TEST_EMAIL = "test@edx.org"
def
update_email_marketing_config
(
enabled
=
True
,
key
=
'badkey'
,
secret
=
'badsecret'
,
new_user_list
=
'new list'
,
template
=
'
Activation
'
,
enroll_cost
=
100
,
lms_url_override
=
'http://testserver'
):
template
=
'
Welcome
'
,
enroll_cost
=
100
,
lms_url_override
=
'http://testserver'
):
"""
Enable / Disable Sailthru integration
"""
...
...
@@ -50,7 +50,7 @@ def update_email_marketing_config(enabled=True, key='badkey', secret='badsecret'
sailthru_key
=
key
,
sailthru_secret
=
secret
,
sailthru_new_user_list
=
new_user_list
,
sailthru_
activation
_template
=
template
,
sailthru_
welcome
_template
=
template
,
sailthru_enroll_template
=
'enroll_template'
,
sailthru_lms_url_override
=
lms_url_override
,
sailthru_get_tags_from_sailthru
=
False
,
...
...
@@ -175,7 +175,7 @@ class EmailMarketingTests(TestCase):
@patch
(
'email_marketing.tasks.SailthruClient.api_get'
)
def
test_add_user
(
self
,
mock_sailthru_get
,
mock_sailthru_post
,
mock_log_error
):
"""
test async method in tasks that actually updates Sailthru
test async method in tasks that actually updates Sailthru
and send Welcome template.
"""
site_dict
=
{
'id'
:
self
.
site
.
id
,
'domain'
:
self
.
site
.
domain
,
'name'
:
self
.
site
.
name
}
mock_sailthru_post
.
return_value
=
SailthruResponse
(
JsonResponse
({
'ok'
:
True
}))
...
...
@@ -183,15 +183,13 @@ class EmailMarketingTests(TestCase):
update_user
.
delay
(
{
'gender'
:
'm'
,
'username'
:
'test'
,
'activated'
:
1
},
TEST_EMAIL
,
site_dict
,
new_user
=
True
)
expected_schedule
=
datetime
.
datetime
.
utcnow
()
+
datetime
.
timedelta
(
seconds
=
600
)
self
.
assertFalse
(
mock_log_error
.
called
)
self
.
assertEquals
(
mock_sailthru_post
.
call_args
[
0
][
0
],
"
user
"
)
self
.
assertEquals
(
mock_sailthru_post
.
call_args
[
0
][
0
],
"
send
"
)
userparms
=
mock_sailthru_post
.
call_args
[
0
][
1
]
self
.
assertEquals
(
userparms
[
'key'
],
"email"
)
self
.
assertEquals
(
userparms
[
'id'
],
TEST_EMAIL
)
self
.
assertEquals
(
userparms
[
'vars'
][
'gender'
],
"m"
)
self
.
assertEquals
(
userparms
[
'vars'
][
'username'
],
"test"
)
self
.
assertEquals
(
userparms
[
'vars'
][
'activated'
],
1
)
self
.
assertEquals
(
userparms
[
'lists'
][
'new list'
],
1
)
self
.
assertEquals
(
userparms
[
'email'
],
TEST_EMAIL
)
self
.
assertEquals
(
userparms
[
'template'
],
"Welcome"
)
self
.
assertEquals
(
userparms
[
'schedule_time'
],
expected_schedule
.
strftime
(
'
%
Y-
%
m-
%
dT
%
H:
%
M:
%
SZ'
))
@patch
(
'email_marketing.tasks.SailthruClient.api_post'
)
@patch
(
'email_marketing.tasks.SailthruClient.api_get'
)
...
...
@@ -199,6 +197,8 @@ class EmailMarketingTests(TestCase):
"""
test non existing domain name updates Sailthru user lists with default list
"""
# Set template to empty string to disable 2nd post call to Sailthru
update_email_marketing_config
(
template
=
''
)
existing_site
=
Site
.
objects
.
create
(
domain
=
'testing.com'
,
name
=
'testing.com'
)
site_dict
=
{
'id'
:
existing_site
.
id
,
'domain'
:
existing_site
.
domain
,
'name'
:
existing_site
.
name
}
mock_sailthru_post
.
return_value
=
SailthruResponse
(
JsonResponse
({
'ok'
:
True
}))
...
...
@@ -216,18 +216,16 @@ class EmailMarketingTests(TestCase):
@patch
(
'email_marketing.tasks.SailthruClient.api_get'
)
def
test_user_activation
(
self
,
mock_sailthru_get
,
mock_sailthru_post
):
"""
test send of activation template
Test that welcome template not sent if not new user.
"""
mock_sailthru_post
.
return_value
=
SailthruResponse
(
JsonResponse
({
'ok'
:
True
}))
mock_sailthru_get
.
return_value
=
SailthruResponse
(
JsonResponse
({
'lists'
:
[{
'name'
:
'new list'
}],
'ok'
:
True
}))
expected_schedule
=
datetime
.
datetime
.
utcnow
()
+
datetime
.
timedelta
(
seconds
=
600
)
update_user
.
delay
({},
self
.
user
.
email
,
new_user
=
True
,
activation
=
True
)
update_user
.
delay
({},
self
.
user
.
email
,
new_user
=
False
)
# look for call args for 2nd call
self
.
assertEquals
(
mock_sailthru_post
.
call_args
[
0
][
0
],
"
send
"
)
self
.
assertEquals
(
mock_sailthru_post
.
call_args
[
0
][
0
],
"
user
"
)
userparms
=
mock_sailthru_post
.
call_args
[
0
][
1
]
self
.
assertEquals
(
userparms
[
'email'
],
TEST_EMAIL
)
self
.
assertEquals
(
userparms
[
'template'
],
"Activation"
)
self
.
assertEquals
(
userparms
[
'schedule_time'
],
expected_schedule
.
strftime
(
'
%
Y-
%
m-
%
dT
%
H:
%
M:
%
SZ'
))
self
.
assertIsNone
(
userparms
.
get
(
'email'
))
self
.
assertIsNone
(
userparms
.
get
(
'template'
))
@patch
(
'email_marketing.tasks.log.error'
)
@patch
(
'email_marketing.tasks.SailthruClient.api_post'
)
...
...
@@ -248,14 +246,14 @@ class EmailMarketingTests(TestCase):
# force Sailthru API exception on 2nd call
mock_log_error
.
reset_mock
()
mock_sailthru
.
side_effect
=
[
SailthruResponse
(
JsonResponse
({
'ok'
:
True
})),
SailthruClientError
]
update_user
.
delay
({},
self
.
user
.
email
,
activation
=
True
)
update_user
.
delay
({},
self
.
user
.
email
,
new_user
=
True
)
self
.
assertTrue
(
mock_log_error
.
called
)
# force Sailthru API error return on 2nd call
mock_log_error
.
reset_mock
()
mock_sailthru
.
side_effect
=
[
SailthruResponse
(
JsonResponse
({
'ok'
:
True
})),
SailthruResponse
(
JsonResponse
({
'error'
:
100
,
'errormsg'
:
'Got an error'
}))]
update_user
.
delay
({},
self
.
user
.
email
,
activation
=
True
)
update_user
.
delay
({},
self
.
user
.
email
,
new_user
=
True
)
self
.
assertTrue
(
mock_log_error
.
called
)
@patch
(
'email_marketing.tasks.update_user.retry'
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment