mirror of
https://github.com/we-promise/sure.git
synced 2026-05-30 15:59:02 +00:00
Lays the foundation for Retirement v2 as a preview feature stacked on Goals v2. Math, lens UI, pension sources and bucket all defer to later PRs; this PR ships only the data-model spine and a placeholder landing. - STI on goals: add `type` (default "Goal") + `user_id` columns; partial index for `Goal::Retirement` rows; check constraint requiring an owner on retirement rows. Existing goals backfill to `type='Goal'`; base `Goal#editable_by?` stays family-scoped. - `Goal::Retirement` subclass with single-user owner and `editable_by?` narrowed to owner-only. Parent depository-only linked-account validations no-op'd; PR2 introduces `RetirementBucketEntry`. - `families.retirement_disabled` killswitch (default false) + `Family#retirement_enabled?(user)` helper as tier 2 of the gate. Tier 1 is the existing `PreviewGateable` flow. - `RetirementController#show`: `require_preview_features!` then `ensure_module_enabled!` then a placeholder body. Unknown to users without preview features; 404 when the family killswitch is on (the feature behaves as if it does not exist). - Sidebar: new `sun`-icon entry after Goals, hidden unless the user has preview features AND the family has retirement enabled, so the killswitch hides the nav rather than leaving a link that 404s. - Locales: EN copy for nav, breadcrumb, page header, placeholder body, and the new `owner.must_belong_to_family` validation message under the goal model. DE deferred to PR4. - Tests: STI roundtrip, owner presence + family-membership validations, `editable_by?` on both Goal and Goal::Retirement, gate matrix on the controller, nav-item visibility under both preview and family flags, base-row STI backfill. Stack ahead: PR2 ships the data plane (PensionSource, statements, adjustments, bucket entries); PR3 wires the `Retirement::Fire::*` forecast engine + WHAT-IF Turbo Stream slider loop; PR4 lands the single combined-page UI per Claude's 2026-05-29 design (glide chart with hover-tooltip income breakdown, no separate stacked-area chart).
27 lines
701 B
Ruby
27 lines
701 B
Ruby
class RetirementController < ApplicationController
|
|
include PreviewGateable
|
|
|
|
before_action :require_preview_features!
|
|
before_action :ensure_module_enabled!
|
|
before_action :load_goal_retirement
|
|
|
|
def show
|
|
@breadcrumbs = [
|
|
[ t("breadcrumbs.home"), root_path ],
|
|
[ t("breadcrumbs.retirement"), nil ]
|
|
]
|
|
end
|
|
|
|
private
|
|
def ensure_module_enabled!
|
|
return if Current.family.retirement_enabled?(Current.user)
|
|
raise ActionController::RoutingError, "Not Found"
|
|
end
|
|
|
|
def load_goal_retirement
|
|
@goal = Current.family.goals
|
|
.where(type: "Goal::Retirement", user_id: Current.user.id)
|
|
.first
|
|
end
|
|
end
|