Skip to content

Commit

Permalink
Missing reimbursement reminders
Browse files Browse the repository at this point in the history
  • Loading branch information
ancorgs committed Jul 1, 2014
1 parent 88d48e8 commit de5a2d6
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 0 deletions.
7 changes: 7 additions & 0 deletions app/mailers/request_mailer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class RequestMailer < ApplicationMailer

def missing_reimbursement(to, request)
@request = request
mail(:to => to, :subject => t(:mailer_subject_missing_reimbursement, :request => @request.title))
end
end
27 changes: 27 additions & 0 deletions app/models/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,33 @@ def self.expenses_sum(attr = :total, requests)
RequestExpense.by_attr_for_requests(attr, r_ids).sum(amount_field)
end

# Sends notifications about requests lacking a reimbursement.
#
# Looks for events that finished some days ago or that are about to reach the
# reimbursement deadline and sends a reminder for every request associated to
# those events and lacking a reimbursement object.
#
# @param [#to_i] after_end_threshold number of days after the event to start
# sending reminders
# @param [#to_i] before_deadline_threshold number of days before the
# reimbursement deadline to start sending reminders
def self.notify_missing_reimbursement(after_end_threshold, before_deadline_threshold)
now = Time.zone.now
# Skip events finished more than 6 months ago to keep the size under control
candidate_events = Event.where(
[ "(end_date > ? and end_date < ?) or "\
"(reimbursement_creation_deadline > ? and reimbursement_creation_deadline < ?)",
now - 6.months, now - after_end_threshold, now, now + before_deadline_threshold])
candidate_events.includes(:requests).each do |e|
e.requests.each do |r|
if r.lacks_reimbursement?
users = [r.user] + Request.responsible_roles
RequestMailer::notify_to(users, :missing_reimbursement, r)
end
end
end
end

protected

def only_one_active_request
Expand Down
8 changes: 8 additions & 0 deletions app/views/request_mailer/missing_reimbursement.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<p><%= t(:missing_reimbursement_text, :request => @request.title) %></p>

<p><%= link_to(*[request_url(@request)]*2) %></p>

<p><%= t(:missing_reimbursement_advise) %></p>

<p>--<br>
<%= TravelSupport::Config.setting :email_footer %></p>
8 changes: 8 additions & 0 deletions app/views/request_mailer/missing_reimbursement.text.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<%= t(:missing_reimbursement_text, :request => @request.title) %>
<%= request_url(@request) %>
<%= t(:missing_reimbursement_advise) %>

--
<%= TravelSupport::Config.setting :email_footer %>
5 changes: 5 additions & 0 deletions config/locales/mailers.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,10 @@ en:
machine_in_state: "%{machine} is in %{state} (%{description}) state since %{date}"
visit_machine: "To access the related information, just follow the link below:"
with_notes_below: "with the following notes:"

mailer_subject_new_comment: "New comment on %{machine}"
new_comment_title_line: "At %{date}, %{user} added the following comment to %{machine}"

mailer_subject_missing_reimbursement: "Missing reimbursement for %{request}"
missing_reimbursement_text: "No reimbursement has been created for %{request}. Remember that the reimbursement process can be started using the 'ask for reimbursement' button in the request view."
missing_reimbursement_advise: "You will keep receiving this daily reminder as long as the reimbursement period is open and no reimbursement has been created. If the requester has decided to renounce the reimbursement, maybe the best option is to actually create the reimbursement and then cancel it stating the reason."
3 changes: 3 additions & 0 deletions config/site.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ common: &common
budget_limits: true

days_for_reminder: 3
reimbursement_reminder:
days_after_event: 5
days_before_deadline: 5
async_emails: true
email_from: "Travel Support Program <noreply@example.com>"
email_footer: "Travel Support Program"
Expand Down
6 changes: 6 additions & 0 deletions script/clockwork.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,11 @@ module Clockwork
Request.notify_inactive_since date
Reimbursement.notify_inactive_since date
end

end_threshold = TravelSupport::Config.setting(:reimbursement_reminder, :days_after_event)
deadline_threshold = TravelSupport::Config.setting(:reimbursement_reminder, :days_before_deadline)
unless end_threshold.blank? || deadline_threshold.blank?
Request.notify_missing_reimbursement end_threshold.to_i.days, deadline_threshold.to_i.days
end
end
end
48 changes: 48 additions & 0 deletions spec/models/request_mailer_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
require 'spec_helper'
#require 'ruby-debug'

describe RequestMailer do
fixtures :all

context "notifying missing reimbursements with a narrow threshold" do
before(:each) do
@mcount = ActionMailer::Base.deliveries.size
Request.notify_missing_reimbursement 1.day, 10.days
@request = requests(:luke_for_yavin)
@mails = ActionMailer::Base.deliveries[-3..-1]
end

it "should mail requester, tsp and assistant" do
ActionMailer::Base.deliveries.size.should == @mcount + 3
@mails.map(&:to).flatten.should include @request.user.email
end

it "should include request url in the mail body" do
@mails.first.body.encoded.should match "http.+/requests/#{@request.id}"
end
end

context "notifying missing reimbursements with a big threshold" do
before(:each) do
@mcount = ActionMailer::Base.deliveries.size
Request.notify_missing_reimbursement 10.days, 11.days
end

it "should mail nobody" do
ActionMailer::Base.deliveries.size.should == @mcount
end
end

context "notifying missing reimbursements based on reimbursement deadline" do
before(:each) do
@mcount = ActionMailer::Base.deliveries.size
event = events(:yavin_hackaton)
event.update_attribute(:reimbursement_creation_deadline, 10.days.since)
Request.notify_missing_reimbursement 10.days, 11.days
end

it "should mail requester, tsp and assistant" do
ActionMailer::Base.deliveries.size.should == @mcount+3
end
end
end

0 comments on commit de5a2d6

Please sign in to comment.