Add scholarship decline flow with admin email and totals exclusion - #2178
Draft
maebeale wants to merge 9 commits into
Draft
Add scholarship decline flow with admin email and totals exclusion#2178maebeale wants to merge 9 commits into
maebeale wants to merge 9 commits into
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>
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: 5 Inspect 🔬 new agreement state model + data migration + history model that alter financial totals across dashboards, grant budgets, revenue/scholarship reports, and many display surfaces
What is the goal of this PR and why is this important?
How did you approach the change?
agreement_signed_at/agreement_declined_at/ reason withagreement_response_status+agreement_responded_at+agreement_response_reason(data migration backfills existing rows). Predicates (agreement_signed?/agreement_declined?) are unchanged for the ~16 call sites that use them.ScholarshipAgreementResponsemodel — one append-only row per transition (status, reason, responder, amount at the time), seeded for existing decided awards. Shown as a collapsible timeline on the scholarship edit page.<details>reason box next to Agree; recording a decline zeroes the allocation (so all allocation-based totals self-correct) and appends a history row. Newscholarship_agreement_declined_fyiNotification kind →NotificationMailer+ views + preview..not_declinedon theamount_cents/scope readers (grant budget/remaining, funding split, EventDashboard, EventScholarshipFigures, EventRevenueFigures, ScholarshipsGrouping, grant decorator counts, registrant badge).scholarship-decline-guardStimulus controller warns before either action discards a decline.Anything else to add?
scholarship_agreement_responses.bin/brakeman --ensure-latestfails only because installed Brakeman 8.0.5 is behind the just-released 8.0.6;bundle exec brakemanscans clean (0 warnings).