Conversation
My thought is that 10am Eastern is a fair time to expect a timer to have started, considering the expectation of attendance at the 9:30am standup. Also, because the standup is always at 9:30am Eastern time, we might be able to punt for now on sending these reminders in the user's time zone. |
This allows us to check timers at multiple times throughout the day without spamming people. This is especially useful so that we can time the email deliveries based on factors like the user's time zone or the application time zone's current UTC offset.
|
||
def call | ||
User.all.each do |user| | ||
next if user.timer_reminder_sent_on.try(:today?) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can do al this in SQL, because if you pass a TimeWithZone
into a query, Rails will figure out the TZ stuff for you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
User.where.not(timer_reminder_sent_on: Date.today)
i think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🆒, I'll drop that in and see if it's 💚.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💣 The problem is that we want to continue past line 11 if the user's never had a timer reminder set, as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or to the rescue!
User.where("timer_reminder_sent_on < ? OR timer_reminder_sent_on IS NULL", Date.current)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that performs an inner join so would only match users that have days recorded in hourglass.
The pto check is a more complicated query
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok @laserlemon you're going to hate this and @trestrantham is going to love it ;)
User.where("timer_reminder_sent_on < ? OR timer_reminder_sent_on IS NULL", context.date).
joins(
User.arel_table.join(Day.arel_table, Arel::Nodes::OuterJoin).on(
Day.arel_table[:user_id].eq(User.arel_table[:id]).and(
Day.arel_table[:date].eq(context.date).and(Day.arel_table[:pto].eq(false))
)
).join_sources
)
Tests pass with this locally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ha! Remember what I said about clarity?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to go the route of assuming that the user already has a day recorded because of how often new hours are fetched for the day and because of how this particular interactor is scheduled for later in the morning. That also gives us the benefit of not having to call out to Harvest so we can keep this all in the model.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated in 9b74755.
👀 🙏 |
Have you thought about putting the "sent" flag on the |
@danielmorrison What do you mean by the "sent" flag? |
Tracking when you sent the reminder Daniel Morrison
|
Oh, that's an interesting thought. I'll take a look when I have some time. |
Yeah, storing that on the day is way better. Great idea. Implementing now. |
timer_reminder_sent: false | ||
) | ||
end | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@danielmorrison I think this makes a lot more sense for querying for timer reminders.
❔ |
This ensures that nobody gets a timer reminder email before he or she is expected to be working.
This information will be used in analytics and in determining whether to send timer reminders to users.
This will be used to parse the PTO calendar provided by Zenefits.
This will run periodically to keep Hourglass in step with Zenefits, and should run before timer reminders are sent out so that nobody is sent a timer reminder on his or her day off.
The last thing we want to do is bug somebody on vacation!
This should be able to be run from the console for any day you like.
Rather than making an external call to Harvest, we can rely on the data we have being up to date enough to determine whether a user has started a timer yet today. This also removes the ability for this particular interactor to be callable with a custom date because it doesn't make as much sense in this context as it does for an interactor like FetchDailyHours. The change also fixes a bug where a user's timer_reminder_sent_on column was updated even if no reminder was necessary.
…rather than users. This makes it much easier to keep track of several days that have already had reminders sent, rather than just the last one.
This now makes more sense as timer reminders are controlled by individual days themselves rather than by user records.
dc944c3
to
c27529b
Compare
This is now deployed for "real world" testing. |
Send timer reminder emails
If a user hasn't started a timer by a configured time in the morning, he or she receives an email reminder to either start a timer or to update the Zenefits PTO calendar. If the user already has PTO scheduled in the Zenefits calendar, a reminder is never sent.
TODO
Send reminders at the specified time in the user's time zonerake hourglass:send_timer_reminders
on Heroku schedulerZENEFITS_PTO_CALENDAR_URL
in productionrake hourglass:sync_pto
on Heroku scheduler