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
58bff7ed
Commit
58bff7ed
authored
Oct 24, 2017
by
Gabe Mulley
Committed by
Calen Pennington
Oct 24, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
update docstrings, DRY up schedules_for_bin
parent
1accff9b
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
73 additions
and
59 deletions
+73
-59
openedx/core/djangoapps/schedules/resolvers.py
+73
-59
No files found.
openedx/core/djangoapps/schedules/resolvers.py
View file @
58bff7ed
...
@@ -40,16 +40,29 @@ COURSE_UPDATE_NUM_BINS = DEFAULT_NUM_BINS
...
@@ -40,16 +40,29 @@ COURSE_UPDATE_NUM_BINS = DEFAULT_NUM_BINS
@attr.s
@attr.s
class
BinnedSchedulesBaseResolver
(
PrefixedDebugLoggerMixin
,
RecipientResolver
):
class
BinnedSchedulesBaseResolver
(
PrefixedDebugLoggerMixin
,
RecipientResolver
):
"""
"""
Starts num_bins number of async tasks, each of which sends emails to an equal group of learners.
Identifies learners to send messages to, pulls all needed context and sends a message to each learner.
Note that for performance reasons, it actually enqueues a task to send the message instead of sending the message
directly.
Arguments:
Arguments:
async_send_task -- celery task function that sends the message
site -- Site object that filtered Schedules will be a part of
site -- Site object that filtered Schedules will be a part of
current_date -- datetime that will be used (with time zeroed-out) as the current date in the queries
target_datetime -- datetime that the User's Schedule's schedule_date_field value should fall under
async_send_task -- celery task function which this resolver will call out to
day_offset -- int number of days relative to the Schedule's schedule_date_field that we are targeting
bin_num -- int for selecting the bin of Users whose id
%
num_bins == bin_num
org_list -- list of course_org names (strings) that the returned Schedules must or must not be in
(default: None)
exclude_orgs -- boolean indicating whether the returned Schedules should exclude (True) the course_orgs in
org_list or strictly include (False) them (default: False)
override_recipient_email -- string email address that should receive all emails instead of the normal
recipient. (default: None)
Static attributes:
Static attributes:
schedule_date_field -- the name of the model field that represents the date that offsets should be computed
relative to. For example, if this resolver finds schedules that started 7 days ago
this variable should be set to "start".
num_bins -- the int number of bins to split the users into
num_bins -- the int number of bins to split the users into
enqueue_config_var -- the string field name of the config variable on ScheduleConfig to check before enqueuing
"""
"""
async_send_task
=
attr
.
ib
()
async_send_task
=
attr
.
ib
()
site
=
attr
.
ib
()
site
=
attr
.
ib
()
...
@@ -87,14 +100,6 @@ class BinnedSchedulesBaseResolver(PrefixedDebugLoggerMixin, RecipientResolver):
...
@@ -87,14 +100,6 @@ class BinnedSchedulesBaseResolver(PrefixedDebugLoggerMixin, RecipientResolver):
Returns Schedules with the target_date, related to Users whose id matches the bin_num, and filtered by org_list.
Returns Schedules with the target_date, related to Users whose id matches the bin_num, and filtered by org_list.
Arguments:
Arguments:
schedule_date_field -- string field name to query on the User's Schedule model
current_datetime -- datetime that will be used as "right now" in the query
target_datetime -- datetime that the User's Schedule's schedule_date_field value should fall under
bin_num -- int for selecting the bin of Users whose id
%
num_bins == bin_num
num_bin -- int specifying the number of bins to separate the Users into (default: DEFAULT_NUM_BINS)
org_list -- list of course_org names (strings) that the returned Schedules must or must not be in (default: None)
exclude_orgs -- boolean indicating whether the returned Schedules should exclude (True) the course_orgs in org_list
or strictly include (False) them (default: False)
order_by -- string for field to sort the resulting Schedules by
order_by -- string for field to sort the resulting Schedules by
"""
"""
target_day
=
_get_datetime_beginning_of_day
(
self
.
target_datetime
)
target_day
=
_get_datetime_beginning_of_day
(
self
.
target_datetime
)
...
@@ -148,17 +153,7 @@ class BinnedSchedulesBaseResolver(PrefixedDebugLoggerMixin, RecipientResolver):
...
@@ -148,17 +153,7 @@ class BinnedSchedulesBaseResolver(PrefixedDebugLoggerMixin, RecipientResolver):
return
schedules
return
schedules
class
ScheduleStartResolver
(
BinnedSchedulesBaseResolver
):
"""
Send a message to all users whose schedule started at ``self.current_date`` + ``day_offset``.
"""
log_prefix
=
'Scheduled Nudge'
schedule_date_field
=
'start'
num_bins
=
RECURRING_NUDGE_NUM_BINS
def
schedules_for_bin
(
self
):
def
schedules_for_bin
(
self
):
schedules
=
self
.
get_schedules_with_target_date_by_bin_and_orgs
()
schedules
=
self
.
get_schedules_with_target_date_by_bin_and_orgs
()
template_context
=
get_base_template_context
(
self
.
site
)
template_context
=
get_base_template_context
(
self
.
site
)
...
@@ -166,15 +161,11 @@ class ScheduleStartResolver(BinnedSchedulesBaseResolver):
...
@@ -166,15 +161,11 @@ class ScheduleStartResolver(BinnedSchedulesBaseResolver):
user_schedules
=
list
(
user_schedules
)
user_schedules
=
list
(
user_schedules
)
course_id_strs
=
[
str
(
schedule
.
enrollment
.
course_id
)
for
schedule
in
user_schedules
]
course_id_strs
=
[
str
(
schedule
.
enrollment
.
course_id
)
for
schedule
in
user_schedules
]
first_schedule
=
user_schedules
[
0
]
# This is used by the bulk email optout policy
template_context
.
update
({
template_context
[
'course_ids'
]
=
course_id_strs
'student_name'
:
user
.
profile
.
name
,
'course_name'
:
first_schedule
.
enrollment
.
course
.
display_name
,
'course_url'
:
absolute_url
(
self
.
site
,
reverse
(
'course_root'
,
args
=
[
str
(
first_schedule
.
enrollment
.
course_id
)])),
# This is used by the bulk email optout policy
first_schedule
=
user_schedules
[
0
]
'course_ids'
:
course_id_strs
,
template_context
.
update
(
self
.
get_template_context
(
user
,
user_schedules
))
})
# Information for including upsell messaging in template.
# Information for including upsell messaging in template.
_add_upsell_button_information_to_template_context
(
_add_upsell_button_information_to_template_context
(
...
@@ -182,6 +173,42 @@ class ScheduleStartResolver(BinnedSchedulesBaseResolver):
...
@@ -182,6 +173,42 @@ class ScheduleStartResolver(BinnedSchedulesBaseResolver):
yield
(
user
,
first_schedule
.
enrollment
.
course
.
language
,
template_context
)
yield
(
user
,
first_schedule
.
enrollment
.
course
.
language
,
template_context
)
def
get_template_context
(
self
,
user
,
user_schedules
):
"""
Given a user and their schedules, build the context needed to render the template for this message.
Arguments:
user -- the User who will be receiving the message
user_schedules -- a list of Schedule objects representing all of their schedules that should be covered by
this message. For example, when a user enrolls in multiple courses on the same day, we
don't want to send them multiple reminder emails. Instead this list would have multiple
elements, allowing us to send a single message for all of the courses.
Returns:
dict: This dict must be JSON serializable (no datetime objects!). When rendering the message templates it
it will be used as the template context. Note that it will also include several default values that
injected into all template contexts. See `get_base_template_context` for more information.
"""
return
{}
class
ScheduleStartResolver
(
BinnedSchedulesBaseResolver
):
"""
Send a message to all users whose schedule started at ``self.current_date`` + ``day_offset``.
"""
log_prefix
=
'Scheduled Nudge'
schedule_date_field
=
'start'
num_bins
=
RECURRING_NUDGE_NUM_BINS
def
get_template_context
(
self
,
user
,
user_schedules
):
first_schedule
=
user_schedules
[
0
]
return
{
'course_name'
:
first_schedule
.
enrollment
.
course
.
display_name
,
'course_url'
:
absolute_url
(
self
.
site
,
reverse
(
'course_root'
,
args
=
[
str
(
first_schedule
.
enrollment
.
course_id
)])
),
}
def
_get_datetime_beginning_of_day
(
dt
):
def
_get_datetime_beginning_of_day
(
dt
):
"""
"""
...
@@ -198,33 +225,18 @@ class UpgradeReminderResolver(BinnedSchedulesBaseResolver):
...
@@ -198,33 +225,18 @@ class UpgradeReminderResolver(BinnedSchedulesBaseResolver):
schedule_date_field
=
'upgrade_deadline'
schedule_date_field
=
'upgrade_deadline'
num_bins
=
UPGRADE_REMINDER_NUM_BINS
num_bins
=
UPGRADE_REMINDER_NUM_BINS
def
schedules_for_bin
(
self
):
def
get_template_context
(
self
,
user
,
user_schedules
):
schedules
=
self
.
get_schedules_with_target_date_by_bin_and_orgs
()
first_schedule
=
user_schedules
[
0
]
return
{
for
(
user
,
user_schedules
)
in
groupby
(
schedules
,
lambda
s
:
s
.
enrollment
.
user
):
'course_links'
:
[
user_schedules
=
list
(
user_schedules
)
{
course_id_strs
=
[
str
(
schedule
.
enrollment
.
course_id
)
for
schedule
in
user_schedules
]
'url'
:
absolute_url
(
self
.
site
,
reverse
(
'course_root'
,
args
=
[
str
(
s
.
enrollment
.
course_id
)])),
'name'
:
s
.
enrollment
.
course
.
display_name
first_schedule
=
user_schedules
[
0
]
}
for
s
in
user_schedules
template_context
=
get_base_template_context
(
self
.
site
)
],
template_context
.
update
({
'first_course_name'
:
first_schedule
.
enrollment
.
course
.
display_name
,
'student_name'
:
user
.
profile
.
name
,
'cert_image'
:
absolute_url
(
self
.
site
,
static
(
'course_experience/images/verified-cert.png'
)),
'course_links'
:
[
}
{
'url'
:
absolute_url
(
self
.
site
,
reverse
(
'course_root'
,
args
=
[
str
(
s
.
enrollment
.
course_id
)])),
'name'
:
s
.
enrollment
.
course
.
display_name
}
for
s
in
user_schedules
],
'first_course_name'
:
first_schedule
.
enrollment
.
course
.
display_name
,
'cert_image'
:
absolute_url
(
self
.
site
,
static
(
'course_experience/images/verified-cert.png'
)),
# This is used by the bulk email optout policy
'course_ids'
:
course_id_strs
,
})
_add_upsell_button_information_to_template_context
(
user
,
first_schedule
,
template_context
)
yield
(
user
,
first_schedule
.
enrollment
.
course
.
language
,
template_context
)
def
_add_upsell_button_information_to_template_context
(
user
,
schedule
,
template_context
):
def
_add_upsell_button_information_to_template_context
(
user
,
schedule
,
template_context
):
...
@@ -269,6 +281,7 @@ class CourseUpdateResolver(BinnedSchedulesBaseResolver):
...
@@ -269,6 +281,7 @@ class CourseUpdateResolver(BinnedSchedulesBaseResolver):
order_by
=
'enrollment__course'
,
order_by
=
'enrollment__course'
,
)
)
template_context
=
get_base_template_context
(
self
.
site
)
for
schedule
in
schedules
:
for
schedule
in
schedules
:
enrollment
=
schedule
.
enrollment
enrollment
=
schedule
.
enrollment
try
:
try
:
...
@@ -279,11 +292,12 @@ class CourseUpdateResolver(BinnedSchedulesBaseResolver):
...
@@ -279,11 +292,12 @@ class CourseUpdateResolver(BinnedSchedulesBaseResolver):
user
=
enrollment
.
user
user
=
enrollment
.
user
course_id_str
=
str
(
enrollment
.
course_id
)
course_id_str
=
str
(
enrollment
.
course_id
)
template_context
=
get_base_template_context
(
self
.
site
)
template_context
.
update
({
template_context
.
update
({
'student_name'
:
user
.
profile
.
name
,
'student_name'
:
user
.
profile
.
name
,
'course_name'
:
schedule
.
enrollment
.
course
.
display_name
,
'course_name'
:
schedule
.
enrollment
.
course
.
display_name
,
'course_url'
:
absolute_url
(
self
.
site
,
reverse
(
'course_root'
,
args
=
[
str
(
schedule
.
enrollment
.
course_id
)])),
'course_url'
:
absolute_url
(
self
.
site
,
reverse
(
'course_root'
,
args
=
[
str
(
schedule
.
enrollment
.
course_id
)])
),
'week_num'
:
week_num
,
'week_num'
:
week_num
,
'week_summary'
:
week_summary
,
'week_summary'
:
week_summary
,
...
...
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