1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-08-05 13:35:21 +02:00

Add income and spending insight cards to dashboard (#668)

* Generate time series for rolling 30 day sum of income and spending

* Highlight accounts with most income and spending in the last 30 days

* Aggregate chips after 3 top accounts in insight card

* Refactor aggregation filter

I think this is easier to read and understand whats happening at a
glance

* Refactor and tidy

* Use family currency for insight cards

* Further reduce risk of sql injection

* Fix lint

* Refactor rolling total queries

* Add test for transaction snapshot
This commit is contained in:
Josh Brown 2024-04-24 13:34:50 +01:00 committed by GitHub
parent 1f6e83ee91
commit 461fa672ff
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 207 additions and 64 deletions

View file

@ -28,6 +28,49 @@ class Family < ApplicationRecord
}
end
def snapshot_account_transactions
period = Period.last_30_days
results = accounts.active.joins(:transactions)
.select(
"accounts.*",
"COALESCE(SUM(amount) FILTER (WHERE amount > 0), 0) AS spending",
"COALESCE(SUM(-amount) FILTER (WHERE amount < 0), 0) AS income"
)
.where("transactions.date >= ?", period.date_range.begin)
.where("transactions.date <= ?", period.date_range.end)
.group("id")
.to_a
{
top_spenders: results.sort_by(&:spending).select { |a| a.spending > 0 }.reverse,
top_earners: results.sort_by(&:income).select { |a| a.income > 0 }.reverse
}
end
def snapshot_transactions
rolling_totals = Transaction.daily_rolling_totals(transactions, period: Period.last_30_days, currency: self.currency)
spending = []
income = []
rolling_totals.each do |r|
spending << {
date: r.date,
value: Money.new(r.rolling_spend, self.currency)
}
income << {
date: r.date,
value: Money.new(r.rolling_income, self.currency)
}
end
{
income_series: TimeSeries.new(income, favorable_direction: "up"),
spending_series: TimeSeries.new(spending, favorable_direction: "down")
}
end
def effective_start_date
accounts.active.joins(:balances).minimum("account_balances.date") || Date.current
end