Skip to content

Commit

Permalink
Send in app notification to volunteer and supervisor on reimbursement…
Browse files Browse the repository at this point in the history
… complete checkbox selection (#5121)


---------

Co-authored-by: Sam Williams <[email protected]>
  • Loading branch information
schoork and Sam Williams authored Oct 8, 2023
1 parent a9b3fcf commit 2cf6c0b
Show file tree
Hide file tree
Showing 11 changed files with 175 additions and 1 deletion.
1 change: 1 addition & 0 deletions .allow_skipping_tests
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ notifications/delivery_methods/sms.rb
notifications/emancipation_checklist_reminder_notification.rb
notifications/followup_notification.rb
notifications/followup_resolved_notification.rb
notifications/reimbursement_complete_notification.rb
notifications/youth_birthday_notification.rb
policies/fund_request_policy.rb
policies/learning_hour_policy.rb
Expand Down
3 changes: 3 additions & 0 deletions app/controllers/reimbursements_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ def change_complete_status
@grouped_case_contacts = fetch_reimbursements
.where({occurred_at: @case_contact.occurred_at, creator_id: @case_contact.creator_id})
@grouped_case_contacts.update_all(reimbursement_params.to_h)
notification_recipients = [@case_contact.creator]
notification_recipients << @case_contact.supervisor if @case_contact.supervisor
ReimbursementCompleteNotification.with(case_contact: @case_contact).deliver(notification_recipients)
redirect_to reimbursements_path unless params[:ajax]
end

Expand Down
11 changes: 11 additions & 0 deletions app/models/casa_org.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,17 @@ def generate_contact_types_and_hearing_types
end
end

# Given a specific date, returns the active mileage rate.
# If more than one mileage rate is active for a given date, assumes the rate for the most recent date takes precedence.
# For instance, given two mileage rates that are active, one set on January 1, 1970 and one set on January 3, 1970:
# then the active rate for the given date of January 5, 1970 would be the January 3 rate.
# If no rates are active for the given date, will return nil.
# @param date [Date]
# @return [BigDecimal, nil]
def mileage_rate_for_given_date(date)
mileage_rates.where(is_active: true, effective_date: ..date).order(effective_date: :desc).first&.amount
end

def has_alternate_active_banner?(current_banner_id)
banners.where(active: true).where.not(id: current_banner_id).exists?
end
Expand Down
15 changes: 15 additions & 0 deletions app/models/case_contact.rb
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,21 @@ def occurred_at_not_in_future
errors.add(:occurred_at, :invalid, message: "cannot be in the future")
end

# Displays occurred_at in the format January 1, 1970
# @return [String]
def occurred_at_display
occurred_at.strftime("%B %-d, %Y")
end

# Returns the mileage rate if the casa_org has a mileage_rate for the date of the contact. Otherwise returns nil.
# @return [BigDecimal, nil]
def reimbursement_amount
mileage_rate = casa_case.casa_org.mileage_rate_for_given_date(occurred_at.to_datetime)
return nil unless mileage_rate

mileage_rate * miles_driven
end

def reimbursement_only_when_miles_driven
return if miles_driven&.positive? || !want_driving_reimbursement

Expand Down
21 changes: 21 additions & 0 deletions app/notifications/reimbursement_complete_notification.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
class ReimbursementCompleteNotification < BaseNotification
deliver_by :database

param :case_contact

def title
"Reimbursement Approved"
end

def message
case_contact = params[:case_contact]
msg = "Volunteer #{case_contact.creator.display_name}'s request for reimbursement for #{case_contact.miles_driven}mi "
msg += " for $#{case_contact.reimbursement_amount} " if case_contact.reimbursement_amount
msg += "on #{case_contact.occurred_at_display} has been processed and is en route."
msg
end

def url
case_contacts_path(casa_case_id: params[:case_contact].casa_case_id)
end
end
10 changes: 10 additions & 0 deletions spec/factories/notifications.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,15 @@
}
initialize_with { new(params: params) }
end

trait :reimbursement_complete do
type { "ReimbursementCompleteNotification" }
params {
{
case_contact: create(:case_contact)
}
}
initialize_with { new(params: params) }
end
end
end
49 changes: 49 additions & 0 deletions spec/models/casa_org_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -121,5 +121,54 @@
expect(hearing_types_names).to include(*HearingType::DEFAULT_HEARING_TYPES)
end
end

describe "mileage rate for a given date" do
let(:casa_org) { build(:casa_org) }

describe "with a casa org with no rates" do
it "is nil" do
expect(casa_org.mileage_rate_for_given_date(Date.today)).to be_nil
end
end

describe "with a casa org with inactive dates" do
let!(:mileage_rates) do
[
create(:mileage_rate, casa_org: casa_org, effective_date: 10.days.ago, is_active: false),
create(:mileage_rate, casa_org: casa_org, effective_date: 3.days.ago, is_active: false)
]
end

it "is nil" do
expect(casa_org.mileage_rates.count).to eq 2
expect(casa_org.mileage_rate_for_given_date(Date.today)).to be_nil
end
end

describe "with active dates in the future" do
let!(:mileage_rate) { create(:mileage_rate, casa_org: casa_org, effective_date: 3.days.from_now) }

it "is nil" do
expect(casa_org.mileage_rates.count).to eq 1
expect(casa_org.mileage_rate_for_given_date(Date.today)).to be_nil
end
end

describe "with active dates in the past" do
let!(:mileage_rates) do
[
create(:mileage_rate, casa_org: casa_org, amount: 4.50, effective_date: 20.days.ago),
create(:mileage_rate, casa_org: casa_org, amount: 5.50, effective_date: 10.days.ago),
create(:mileage_rate, casa_org: casa_org, amount: 6.50, effective_date: 3.days.ago)
]
end

it "uses the most recent date" do
expect(casa_org.mileage_rate_for_given_date(12.days.ago.to_date)).to eq 4.50
expect(casa_org.mileage_rate_for_given_date(5.days.ago.to_date)).to eq 5.50
expect(casa_org.mileage_rate_for_given_date(Date.today)).to eq 6.50
end
end
end
end
end
19 changes: 19 additions & 0 deletions spec/models/case_contact_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -473,4 +473,23 @@
end
end
end

describe "reimbursement amount" do
let(:case_contact) { build(:case_contact, :wants_reimbursement) }

describe "when casa org has nil mileage_rate_for_given_date" do
it "is nil" do
expect(case_contact.casa_case.casa_org.mileage_rate_for_given_date(case_contact.occurred_at.to_datetime)).to be_nil
expect(case_contact.reimbursement_amount).to be_nil
end
end

describe "when casa org has value for mileage_rate_for_given_date" do
let!(:mileage_rate) { create(:mileage_rate, casa_org: case_contact.casa_case.casa_org, effective_date: 3.days.ago, amount: 5.50) }

it "is multiple of miles driven and mileage rate" do
expect(case_contact.reimbursement_amount).to eq 2508
end
end
end
end
23 changes: 23 additions & 0 deletions spec/notifications/reimbursement_complete_notification_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
require "rails_helper"

RSpec.describe ReimbursementCompleteNotification, type: :model do
describe "message" do
let(:case_contact) { build(:case_contact, :wants_reimbursement) }

describe "with case org with nil mileage rate" do
it "does not include reimbursement amount" do
notification = ReimbursementCompleteNotification.with(case_contact: case_contact)
expect(notification.message).not_to include "$"
end
end

describe "with casa org with active mileage rate" do
let!(:mileage_rate) { create(:mileage_rate, casa_org: case_contact.casa_case.casa_org, amount: 6.50, effective_date: 3.days.ago) }

it "does include reimbursement amount" do
notification = ReimbursementCompleteNotification.with(case_contact: case_contact)
expect(notification.message).to include "$2964"
end
end
end
end
8 changes: 7 additions & 1 deletion spec/requests/reimbursements_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@
let(:admin) { create(:casa_admin) }
let(:casa_org) { admin.casa_org }
let(:case_contact) { create(:case_contact) }
let(:notification_double) { double("ReimbursementCompleteNotification") }

before { sign_in(admin) }
before do
sign_in(admin)
allow(ReimbursementCompleteNotification).to receive(:with).and_return(notification_double)
allow(notification_double).to receive(:deliver)
end

describe "GET /index" do
it "calls ReimbursementPolicy::Scope to filter reimbursements" do
Expand Down Expand Up @@ -35,6 +40,7 @@
describe "PATCH /mark_as_complete" do
it "changes reimbursement status to complete" do
patch reimbursement_mark_as_complete_url(case_contact, case_contact: {reimbursement_complete: true})
expect(ReimbursementCompleteNotification).to(have_received(:with).once.with(**{case_contact: case_contact}))
expect(response).to redirect_to(reimbursements_path)
expect(response).to have_http_status(:redirect)
expect(case_contact.reload.reimbursement_complete).to be_truthy
Expand Down
16 changes: 16 additions & 0 deletions spec/system/notifications/index_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,22 @@
end
end

context "ReimbursementCompleteNotification" do
it "should display a notification on the notifications page" do
case_contact = create(:case_contact, :wants_reimbursement)
volunteer.notifications << create(:notification, :reimbursement_complete, params: {case_contact: case_contact})
sign_in volunteer
visit notifications_path
notification_message = "Volunteer #{case_contact.creator.display_name}'s request for reimbursement for " \
"#{case_contact.miles_driven}mi on #{case_contact.occurred_at_display} has been processed and is " \
"en route."
expect(page).not_to have_text(I18n.t(".notifications.index.no_notifications"))
expect(page).to have_content("Reimbursement Approved")
expect(page).to have_content(notification_message)
expect(page).to have_link(href: case_contacts_path(casa_case_id: casa_case.id))
end
end

context "when there are no notifications" do
it "displays a message to the user" do
sign_in volunteer
Expand Down

0 comments on commit 2cf6c0b

Please sign in to comment.