1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-07-19 13:19:39 +02:00
Maybe/app/models/account.rb
Zach Gollwitzer f904d9d062
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
2024-03-19 09:10:40 -04:00

73 lines
2.1 KiB
Ruby

class Account < ApplicationRecord
include Syncable
include Monetizable
validates :family, presence: true
broadcasts_refreshes
belongs_to :family
has_many :balances, class_name: "AccountBalance"
has_many :valuations
has_many :transactions
monetize :balance
enum :status, { ok: "ok", syncing: "syncing", error: "error" }, validate: true
scope :active, -> { where(is_active: true) }
scope :assets, -> { where(classification: "asset") }
scope :liabilities, -> { where(classification: "liability") }
delegated_type :accountable, types: Accountable::TYPES, dependent: :destroy
before_create :check_currency
def self.ransackable_attributes(auth_object = nil)
%w[name]
end
def balance_on(date)
balances.where("date <= ?", date).order(date: :desc).first&.balance
end
def self.by_provider
# TODO: When 3rd party providers are supported, dynamically load all providers and their accounts
[ { name: "Manual accounts", accounts: all.order(balance: :desc).group_by(&:accountable_type) } ]
end
def self.some_syncing?
exists?(status: "syncing")
end
def series(period = Period.all)
TimeSeries.from_collection(balances.in_period(period), :balance_money)
end
def self.by_group(period = Period.all)
grouped_accounts = { assets: ValueGroup.new("Assets"), liabilities: ValueGroup.new("Liabilities") }
Accountable.by_classification.each do |classification, types|
types.each do |type|
group = grouped_accounts[classification.to_sym].add_child_node(type)
Accountable.from_type(type).includes(:account).each do |accountable|
account = accountable.account
value_node = group.add_value_node(account)
value_node.attach_series(account.series(period))
end
end
end
grouped_accounts
end
private
def check_currency
if self.currency == self.family.currency
self.converted_balance = self.balance
self.converted_currency = self.currency
else
self.converted_balance = ExchangeRate.convert(self.currency, self.family.currency, self.balance)
self.converted_currency = self.family.currency
end
end
end