Skip to content

HOLD: Validate scholarship amount against event registration due#1865

Draft
maebeale wants to merge 1 commit into
mainfrom
maebeale/scholarship-amount-validation
Draft

HOLD: Validate scholarship amount against event registration due#1865
maebeale wants to merge 1 commit into
mainfrom
maebeale/scholarship-amount-validation

Conversation

@maebeale

Copy link
Copy Markdown
Collaborator

What is the goal of this PR and why is this important?

  • Awarding a scholarship larger than the event registration's remaining amount due is invalid, but the app handled it poorly:
    • On update, the amount flows through Scholarship#sync_allocation_amountallocation.update!, where the Allocation over-cost validation raises ActiveRecord::RecordInvalid — an unhandled 500.
    • There was no flash message and no field-level error on the amount input.
  • Note: main already validates the grant budget (within_grant_budget); this PR adds the parallel guard for the event registration amount due, which was not covered.

How did you approach the change?

  • Added a Scholarship#amount_within_event_registration_due validation that runs before save, so create/update fail gracefully (@scholarship.save returns false) instead of reaching the raising update! in the after_update callback.
    • Computes the due as event.cost_cents − other allocations, excluding the scholarship's own allocation so edits don't double-count.
    • Skips grant-only/standalone scholarships (no event-registration allocatable) and non-positive amounts.
    • Formats the amount with the shared MoneyFormatter for consistency with the rest of the UI.
  • Controller: set flash.now[:alert] from the model errors on create/update failure.
  • Form: render an inline red field error directly under the "Scholarship amount" input (the top-of-form shared/errors list was already present on main).

Anything else to add?

  • HOLD: opening as a draft pending confirmation this is still desired given main's recent scholarship/allocation rework. The scholarship-preview Stimulus controller (live "Still owed" preview) is purely cosmetic and never blocks submission, so this server-side validation remains the enforcement; its "other allocated" math matches this validation's "other allocations" computation.
  • Tests: model spec covers below/at/over the due, multi-allocation accounting, and own-allocation exclusion; request spec covers create + update returning 422 with the field error (no more 500), plus a within-due happy path.

🤖 Generated with Claude Code

Saving a scholarship amount above the registration's remaining due
previously raised an unhandled error (or silently over-allocated) via
the Allocation after_update callback. Validate up front on the
scholarship so the user gets a flash message and an inline field error.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Comment thread app/models/scholarship.rb
return if amount_cents <= due_cents

errors.add(:amount_dollars, "cannot exceed the event registration amount due (#{MoneyFormatter.dollars_from_cents(due_cents)})")
end

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 From Claude: Runs before save so create/update fail gracefully here — without it, an over-due amount reaches sync_allocation_amount's allocation.update! in after_update and raises RecordInvalid (500). The where.not(id: allocation.id) excludes this scholarship's own allocation so edits don't double-count.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant