Automated scholarship agreement emails - #2193
Draft
maebeale wants to merge 11 commits into
Draft
Conversation
Recipients can decline a scholarship agreement with a reason from their scholarship page. Declining emails the admin team an FYI, records the reason, zeroes the allocation so the award drops out of every total, and shows a Declined badge everywhere scholarships appear. Editing the award amount re-offers it and clears the decline. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Editing the award amount re-offers the scholarship and discards the recipient's recorded decline; warn the admin before that happens. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the two mutually-exclusive agreement timestamps with a single agreement_response_status (pending/accepted/declined) + responded_at + reason, so the states can't contradict and reinstating is a one-field transition. Add a ScholarshipAgreementResponse audit log capturing each accept/decline/re-offer, shown as a collapsible timeline on the edit page. Signing a declined award now cleanly reinstates it; the decline guard warns before either an amount change or a sign clears a decline. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop the redundant agreement_responded_at / agreement_response_reason cache columns — the latest ScholarshipAgreementResponse is the source of truth (only the status stays denormalized, since totals query it in SQL). Link a decline's response row to the FYI notification it produced. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The agreement history preserves a decline through any reinstatement, so the client-side "confirm before clearing a decline" guard is no longer needed. Drop the Stimulus controller, its form hooks, and system spec. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Editing a declined award's amount no longer silently reactivates it. Reinstating is now a deliberate server-side action: a Re-offer button (button_to POST with Turbo's built-in confirm, no custom JS) sets the award back to pending and re-funds the allocation. Consolidate the declined banner onto the edit page beside the button. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…istration On signing, email the recipient a confirmation with a link back to their ticket and send the team an FYI (both once, on the first sign). The decline page's "contact us" now links to the contact form threaded with the registration, and that FYI email links the team to the registration. Copy fixes and, when the decline reason box is open, hide the Agree button via CSS :has() (no JS). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Collapse the three iterative migrations (which added, reshaped, then trimmed the agreement columns) into two clean ones: create scholarship_agreement_responses (with the notification link), then replace agreement_signed_at with the tri-state agreement_response_status — seeding each signed award's date onto an "accepted" response row. Net schema is unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
No signed agreements exist in production, so the status migration no longer backfills or seeds history — it just adds agreement_response_status (default pending) and drops agreement_signed_at. Zero DML. Render the agreement history on the registrant scholarship callout too, but only for admins and with sky "admin only" styling (registrants never see it). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Keep the decline button + reason and the whole decline/status/history/ re-offer feature here; move all the automated-email machinery (the scholarship agreement signed/declined notification kinds, mailers, views, previews, the controller code that sends them, the response→notification link, and the contact-us registration threading) to a stacked follow-up PR. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Stacked on the decline PR. On decline, email the admin team an FYI. On sign, confirm to the recipient (with a link back to their ticket) and send the team an FYI. Thread the decline page's "contact us" link through to the contact form + FYI so the team lands on the right registration. Adds the notification kinds, mailers + views + previews, the controller wiring, and the contact-us registration threading. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
maebeale
force-pushed
the
maebeale/scholarship-decline-email
branch
from
August 15, 2026 22:53
2e39756 to
6bf5bf4
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖 suggested review level: 3 Read 📖 additive notification/mailer wiring on top of the decline PR
Stacked on #2178 (base =
maebeale/scholarship-decline-email). Merge that first.What
The automated emails split out of #2178:
scholarship_agreement_declined_fyi) with the reason.How
Notificationkinds +NotificationMailermethods + HTML/text views + previews, wired throughNotificationMailerJob;EMAIL_TOPICSentries for the admin filter.events/callouts#sign_agreement/#decline_agreement.No schema changes — purely additive code on top of the decline feature.