Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Send emails to users with localized timezone #61

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
'srv0/yelp_large_assets/3f74899c069c'
'/assets/img/illustrations/mascots/[email protected]'
),
'timezone': 'America/Los_Angeles',
'department': 'Consumer',
'business_title': 'Engineer',
}]
Expand Down Expand Up @@ -229,6 +230,7 @@ def _fake_user():
'office': 'USA: CA SF New Montgomery Office',
'company_profile_url': 'https://www.yelp.com/user_details?userid=nkN_do3fJ9xekchVC-v68A',
},
timezone=user['timezone'],
subscription_preferences=[preferences],
)
user_entity.put()
Expand Down
19 changes: 19 additions & 0 deletions tests/logic/meeting_spec_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,22 @@ def test_get_users_from_spec(database, fake_user):

def test_get_meeting_datetime(database, subscription):
assert get_meeting_datetime(database.specs[0]).hour == 15


def test_get_meeting_datetime_user_timezone(database, fake_user):
fake_user.timezone = 'America/Edmonton'
meeting_time = get_meeting_datetime(database.specs[0], fake_user)

assert meeting_time.tzinfo.zone == fake_user.timezone, (
"The meeting time should be in the user's timezone"
)


def test_get_meeting_datetime_user_no_timezone(database, fake_user):
fake_user.timezone = None
localtime = get_meeting_datetime(database.specs[0], fake_user)

meeting_spec_timezone = database.specs[0].meeting_subscription.get().timezone
assert localtime.tzinfo.zone == meeting_spec_timezone, (
'User has no timezone, the meeting timezone should default to the meeting spec'
)
11 changes: 9 additions & 2 deletions yelp_beans/logic/meeting_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,14 @@ def get_users_from_spec(meeting_spec):
return users


def get_meeting_datetime(meeting_spec):
def get_meeting_datetime(meeting_spec, user=None):
''' Get the meeting datetime for user. If user is specified, the timezone will be the user's
timezone preference. If not specified, the timezone will be the meeting spec's timezone.
'''
if user and user.timezone:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ipwnponies I am a little concerned about this line. This doesn't seem backward compatible. I would expect this to blow up for older models that don't have a timezone property.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should version beans - that way you can't run this code without also picking up the changes to the User model

Copy link
Contributor

@kentwills kentwills May 30, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, we should version. Though I am not sure that addresses the problem here. I think that if we have old records that don't have the timezone entry (our current prod instance) and we update the model and attempt to access user.timezone, it will say that timezone does not exist on the user even though the model is defined properly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't user.timezone just return None then?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If that is the case then we should be gtg. Just want to verify that behavior.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just want to verify that behavior

I leave that in the very capable hands of @ipwnponies :)

meeting_timezone = user.timezone
else:
meeting_timezone = meeting_spec.meeting_subscription.get().timezone

meeting_datetime = meeting_spec.datetime
meeting_timezone = meeting_spec.meeting_subscription.get().timezone
return meeting_datetime.replace(tzinfo=utc).astimezone(timezone(meeting_timezone))
2 changes: 2 additions & 0 deletions yelp_beans/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from __future__ import unicode_literals

from google.appengine.ext import ndb
from pytz import common_timezones


class User(ndb.Model):
Expand All @@ -20,6 +21,7 @@ class User(ndb.Model):
last_name = ndb.StringProperty(indexed=False)
photo_url = ndb.TextProperty()
metadata = ndb.JsonProperty()
timezone = ndb.StringProperty(default='America/Los_Angeles', choices=common_timezones, required=True)
terminated = ndb.BooleanProperty(default=False, required=True)
subscription_preferences = ndb.KeyProperty(
kind="UserSubscriptionPreferences",
Expand Down
9 changes: 5 additions & 4 deletions yelp_beans/send_email.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,9 @@ def send_batch_weekly_opt_in_email(meeting_spec):

for user in users:
if not user.terminated:
meeting_localdatetime = get_meeting_datetime(meeting_spec, user)
logging.info(user)
logging.info(meeting_datetime)
logging.info(meeting_localdatetime)
send_single_email(
user.email,
"Want a yelp-beans meeting this week?",
Expand All @@ -97,8 +98,8 @@ def send_batch_weekly_opt_in_email(meeting_spec):
'first_name': user.first_name,
'office': subscription.office,
'location': subscription.location,
'meeting_day': meeting_datetime.strftime('%A'),
'meeting_time': meeting_datetime.strftime('%I:%M %p %Z'),
'meeting_day': meeting_localdatetime.strftime('%A'),
'meeting_time': meeting_localdatetime.strftime('%I:%M %p %Z'),
'meeting_url': create_url,
'link_to_change_pref': 'https://yelp-beans.appspot.com/'
}
Expand Down Expand Up @@ -129,7 +130,7 @@ def send_match_email(user, participants, meeting_spec):
participants - other people in the meeting
meeting_spec - meeting specification
"""
meeting_datetime = get_meeting_datetime(meeting_spec)
meeting_datetime = get_meeting_datetime(meeting_spec, user)
meeting_datetime_end = meeting_datetime + datetime.timedelta(minutes=30)
subscription = meeting_spec.meeting_subscription.get()

Expand Down