mirror of
https://github.com/we-promise/sure.git
synced 2026-05-30 07:49:01 +00:00
perf + tests(goals): share account-ids across velocity windows + cover gaps
- Family#savings_inflow_windows wraps the current/prior 30d sums in a single helper that memoizes the linked-account-id lookup. The KPI tile on the goals index used to run the join+pluck twice per request. - Replace two instance_variable_set pokes and one any_instance.stubs in the goal/controller tests. Refetching the goal exercises the real request lifecycle and stops the tests from leaning on implementation details. The 'All caught up' assertion now relies on a real reached state (target 1 vs the depository fixture's 5000 balance) rather than stubbing :status. - Add tests covering: hex format validation on Goal#color, AASM cache reset (display_status reads the new state on the same instance after pause!), negative pledge amount rejection, expire! no-op on already- expired pledge, cancel! NotOpenError on non-open pledge, sweep job idempotency on a second pass, and strong-params rejection of state / family_id on goal create.
This commit is contained in:
@@ -58,22 +58,13 @@ class Family < ApplicationRecord
|
||||
# Entry amount convention in Sure: inflow is negative, so flip the sign.
|
||||
# Result is allowed to go negative (net outflow last 30d) so the headline
|
||||
# reflects reality; the controller decides how to render.
|
||||
def savings_inflow_velocity(range: 30.days.ago.to_date..Date.current)
|
||||
# Defensive scope: goal_id is already family-bound (this family's
|
||||
# goals), but pinning family_id keeps cross-family bleed-through
|
||||
# impossible if a goal_account ever ends up pointing at a foreign
|
||||
# account through a future bug.
|
||||
account_ids = accounts
|
||||
.joins(:goal_accounts)
|
||||
.where(goal_accounts: { goal_id: goals.select(:id) })
|
||||
.where(currency: primary_currency_code)
|
||||
.distinct
|
||||
.pluck(:id)
|
||||
return 0 if account_ids.empty?
|
||||
def savings_inflow_velocity(range: 30.days.ago.to_date..Date.current, account_ids: nil)
|
||||
ids = account_ids || goal_linked_account_ids
|
||||
return 0 if ids.empty?
|
||||
|
||||
net = Entry
|
||||
.joins("INNER JOIN transactions ON transactions.id = entries.entryable_id AND entries.entryable_type = 'Transaction'")
|
||||
.where(account_id: account_ids, date: range)
|
||||
.where(account_id: ids, date: range)
|
||||
.where(excluded: false)
|
||||
.merge(Transaction.excluding_pending)
|
||||
.sum(:amount)
|
||||
@@ -81,6 +72,39 @@ class Family < ApplicationRecord
|
||||
-net.to_d
|
||||
end
|
||||
|
||||
# Two velocity windows in a single pair of sums that share one
|
||||
# account-id lookup. The kpi tile on the index reads both the current
|
||||
# 30d window and the prior 30d window; without this helper the
|
||||
# `accounts.joins(:goal_accounts)…pluck(:id)` query runs twice per
|
||||
# request even though the answer is identical.
|
||||
def savings_inflow_windows(window_days: 30, now: Date.current)
|
||||
ids = goal_linked_account_ids
|
||||
{
|
||||
current: savings_inflow_velocity(range: (now - window_days)..now, account_ids: ids),
|
||||
prior: savings_inflow_velocity(range: (now - 2 * window_days)..(now - window_days - 1), account_ids: ids)
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Depository accounts linked to this family's goals, restricted to the
|
||||
# primary currency until FX is added. Memoized for the lifetime of the
|
||||
# Family instance so a single request that reads velocity twice (the
|
||||
# KPI tile uses current vs prior 30d) doesn't re-run the join+pluck.
|
||||
# `accounts` is already scoped by the has_many association, and the
|
||||
# join restricts to this family's goals — so cross-family bleed
|
||||
# remains impossible.
|
||||
def goal_linked_account_ids
|
||||
@goal_linked_account_ids ||= accounts
|
||||
.joins(:goal_accounts)
|
||||
.where(goal_accounts: { goal_id: goals.select(:id) })
|
||||
.where(currency: primary_currency_code)
|
||||
.distinct
|
||||
.pluck(:id)
|
||||
end
|
||||
|
||||
public
|
||||
|
||||
has_many :llm_usages, dependent: :destroy
|
||||
has_many :recurring_transactions, dependent: :destroy
|
||||
|
||||
|
||||
Reference in New Issue
Block a user