Skip to content
Merged
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
5 changes: 4 additions & 1 deletion app/controllers/events/callouts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@ def sign_agreement
if params[:agreement] == "yes"
newly_accepted = !scholarship.agreement_signed?
scholarship.accept_agreement!(by: "recipient")
ScholarshipMailer.accepted_fyi(scholarship).deliver_later if newly_accepted
if newly_accepted
ScholarshipMailer.accepted_fyi(scholarship).deliver_later
ScholarshipMailer.accepted_confirmation(scholarship).deliver_later
end
redirect_to registration_scholarship_path(@event_registration.slug), notice: "Thanks β€” your agreement has been recorded."
else
redirect_to registration_scholarship_path(@event_registration.slug), alert: "Something went wrong recording your agreement. Please try again."
Expand Down
9 changes: 9 additions & 0 deletions app/mailers/scholarship_mailer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ def accepted_fyi(scholarship)
mail(subject: fyi_subject("Scholarship accepted"))
end

# Confirmation to the recipient that their acceptance was recorded, with the
# award amount and a link back to their ticket. Sent to them, not the team.
def accepted_confirmation(scholarship)
assign_agreement(scholarship)
registration = scholarship.allocation&.allocatable
@ticket_url = registration_ticket_url(registration.slug) if registration.is_a?(EventRegistration)
mail(to: @recipient&.preferred_email, subject: "AWBW Portal: Your scholarship agreement is confirmed")
end

private

def assign_agreement(scholarship)
Expand Down
24 changes: 24 additions & 0 deletions app/views/scholarship_mailer/accepted_confirmation.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<h1 style="margin: 0 0 12px;">Your scholarship agreement is confirmed</h1>

<p style="font-size: 15px; line-height: 1.5; color: #374151;">
Thank you<% if @recipient&.first_name.present? %>, <%= @recipient.first_name %><% end %> β€” we've recorded your agreement
to complete your scholarship tasks<% if @event.present? %> for <strong><%= @event.title %></strong><% end %>.
</p>

<div style="text-align: center; background-color: #f3f4f6; border-radius: 6px; padding: 24px; margin: 16px 0;">
<p style="font-size: 12px; text-transform: uppercase; letter-spacing: 0.05em; color: #6b7280; margin: 0 0 4px;">Award confirmed</p>
<p style="font-size: 28px; font-weight: bold; color: #166534; margin: 0;"><%= dollars_from_cents(@scholarship.amount_cents) %></p>
</div>

<% if @ticket_url.present? %>
<p style="margin: 20px 0;">
<a href="<%= @ticket_url %>"
style="display:inline-block;background:#166534;color:#ffffff;
text-decoration:none;padding:12px 20px;border-radius:6px;font-weight:bold;">
View your ticket
</a>
</p>
<p style="font-size: 13px; color: #6b7280;">
Your ticket has your award details, tasks, and next steps.
</p>
<% end %>
10 changes: 10 additions & 0 deletions app/views/scholarship_mailer/accepted_confirmation.text.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Your scholarship agreement is confirmed
=======================================

Thank you<% if @recipient&.first_name.present? %>, <%= @recipient.first_name %><% end %> β€” we've recorded your agreement to complete your scholarship tasks<% if @event.present? %> for <%= @event.title %><% end %>.

Award confirmed: <%= dollars_from_cents(@scholarship.amount_cents) %>

<% if @ticket_url.present? %>View your ticket (award details, tasks, and next steps):
<%= @ticket_url %>
<% end %>
12 changes: 12 additions & 0 deletions config/features.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@

# ── 2026-08 ─────────────────────────────────────────────────────────────────

- name: "Scholarship recipients get an agreement confirmation email"
area: scholarships
display_status: public_facing
released_on: 2026-08-30
action_path: /registration/sample
summary: >-
When a recipient accepts their scholarship agreement, they now get a confirmation
email with the award amount and a link back to their ticket β€” so they have a record
that their acceptance went through, not just the on-page notice.
pro_tips:
- The trainings team still gets its own heads-up on every accept, decline, or support request.

- name: "Navigate a form's pages, and fix the forms list actions"
area: content
display_status: admin_facing
Expand Down
27 changes: 27 additions & 0 deletions spec/mailers/scholarship_mailer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,31 @@
expect(mail.subject).to include(scholarship.recipient.full_name)
end
end

describe "#accepted_confirmation" do
let(:event) { create(:event, cost_cents: 10_000, title: "Healing Circle Training") }
let(:registration) { create(:event_registration, event:) }
let(:scholarship) { create(:scholarship, recipient: registration.registrant, amount_cents: 5_000) }
let(:mail) { described_class.accepted_confirmation(scholarship) }

before do
create(:allocation, source: scholarship, allocatable: registration, amount: 5_000)
scholarship.reload.accept_agreement!
end

it "renders without raising" do
expect { mail.deliver_now }.not_to raise_error
end

it "sends to the recipient, not the trainings/programs team" do
expect(mail.to).to eq([ scholarship.recipient.preferred_email ])
end

it "confirms the agreement in the subject and shows the award and ticket link" do
expect(mail.subject).to include("Your scholarship agreement is confirmed")
body = mail.body.encoded
expect(body).to include("$50")
expect(body).to include(registration.slug)
end
end
end
5 changes: 3 additions & 2 deletions spec/requests/events/callouts_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -722,14 +722,15 @@
expect(scholarship.reload.agreement_signed?).to be(false)
end

it "emails the trainings team on a fresh acceptance, but not on a repeat" do
it "emails the trainings team and the recipient on a fresh acceptance, but not on a repeat" do
expect {
post registration_scholarship_agreement_path(registration.slug), params: { agreement: "yes" }
}.to have_enqueued_mail(ScholarshipMailer, :accepted_fyi)
.and have_enqueued_mail(ScholarshipMailer, :accepted_confirmation)

expect {
post registration_scholarship_agreement_path(registration.slug), params: { agreement: "yes" }
}.not_to have_enqueued_mail(ScholarshipMailer, :accepted_fyi)
}.not_to have_enqueued_mail(ScholarshipMailer, :accepted_confirmation)
end

it "redirects to the scholarship page when there is no awarded scholarship" do
Expand Down
7 changes: 7 additions & 0 deletions test/mailers/previews/scholarship_mailer_preview.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ def accepted_fyi
ScholarshipMailer.accepted_fyi(scholarship)
end

def accepted_confirmation
scholarship = a_scholarship
scholarship.accept_agreement! unless scholarship.agreement_signed?

ScholarshipMailer.accepted_confirmation(scholarship)
end

private

def a_scholarship
Expand Down