mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-07-25 08:09:38 +02:00
Add the ability to "rollup" values in a time series (#554)
* Clean up time series models * Add value group rollup class for summarizing hierarchical data * Integrate new classes * Update UI to use new patterns * Update D3 charts to expect new data format * Clean up account model * More cleanup * Money improvements * Use new money fields * Remove invalid fixture data to avoid orphaned accountables * Update time series to work better with collections * Fix tests and UI bugs
This commit is contained in:
parent
0a8518506c
commit
f904d9d062
34 changed files with 687 additions and 391 deletions
83
app/models/time_series.rb
Normal file
83
app/models/time_series.rb
Normal file
|
@ -0,0 +1,83 @@
|
|||
|
||||
class TimeSeries
|
||||
attr_reader :type
|
||||
|
||||
def self.from_collection(collection, value_method, options = {})
|
||||
data = collection.map do |obj|
|
||||
{ date: obj.date, value: obj.public_send(value_method), original: obj }
|
||||
end
|
||||
new(data, options)
|
||||
end
|
||||
|
||||
def initialize(data, options = {})
|
||||
@type = options[:type] || :normal
|
||||
initialize_series_data(data)
|
||||
end
|
||||
|
||||
def values
|
||||
@values ||= add_trends_to_series
|
||||
end
|
||||
|
||||
def first
|
||||
values.first
|
||||
end
|
||||
|
||||
def last
|
||||
values.last
|
||||
end
|
||||
|
||||
def on(date)
|
||||
values.find { |v| v.date == date }
|
||||
end
|
||||
|
||||
def trend
|
||||
TimeSeries::Trend.new(
|
||||
current: last&.value,
|
||||
previous: first&.value,
|
||||
type: @type
|
||||
)
|
||||
end
|
||||
|
||||
# Data shape that frontend expects for D3 charts
|
||||
def to_json(*_args)
|
||||
{
|
||||
values: values.map do |v|
|
||||
{
|
||||
date: v.date,
|
||||
value: JSON.parse(v.value.to_json),
|
||||
trend: {
|
||||
type: v.trend.type,
|
||||
direction: v.trend.direction,
|
||||
value: JSON.parse(v.trend.value.to_json),
|
||||
percent: v.trend.percent
|
||||
}
|
||||
}
|
||||
end,
|
||||
trend: {
|
||||
type: @type,
|
||||
direction: trend.direction,
|
||||
value: JSON.parse(trend.value.to_json),
|
||||
percent: trend.percent
|
||||
},
|
||||
type: @type
|
||||
}.to_json
|
||||
end
|
||||
|
||||
private
|
||||
def initialize_series_data(data)
|
||||
@series_data = data.nil? || data.empty? ? [] : data.map { |d| TimeSeries::Value.new(d) }.sort_by(&:date)
|
||||
end
|
||||
|
||||
def add_trends_to_series
|
||||
[ nil, *@series_data ].each_cons(2).map do |previous, current|
|
||||
unless current.trend
|
||||
current.trend = TimeSeries::Trend.new(
|
||||
current: current.value,
|
||||
previous: previous&.value,
|
||||
type: @type
|
||||
)
|
||||
end
|
||||
current
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue