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

Account namespace updates: part 5 (valuations) (#901)

* Move Valuation to Account namespace

* Move account history to controller

* Clean up valuation controller and views

* Translations and cleanup

* Remove unused scopes and methods

* Pass brakeman
This commit is contained in:
Zach Gollwitzer 2024-06-21 16:23:28 -04:00 committed by GitHub
parent 0bc0d87768
commit 12380dc8ad
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
45 changed files with 478 additions and 346 deletions

View file

@ -29,6 +29,10 @@ class Account < ApplicationRecord
balances.where("date <= ?", date).order(date: :desc).first&.balance
end
def favorable_direction
classification == "asset" ? "up" : "down"
end
# e.g. Wise, Revolut accounts that have transactions in multiple currencies
def multi_currency?
currencies = [ valuations.pluck(:currency), transactions.pluck(:currency) ].flatten.uniq

View file

@ -0,0 +1,52 @@
class Account::Valuation < ApplicationRecord
include Monetizable
monetize :value
belongs_to :account
validates :account, :date, :value, presence: true
validates :date, uniqueness: { scope: :account_id }
scope :chronological, -> { order(:date) }
scope :reverse_chronological, -> { order(date: :desc) }
def trend
@trend ||= create_trend
end
def first_of_series?
account.valuations.chronological.limit(1).pluck(:date).first == self.date
end
def last_of_series?
account.valuations.reverse_chronological.limit(1).pluck(:date).first == self.date
end
def sync_account_later
if destroyed?
sync_start_date = previous_valuation&.date
else
sync_start_date = [ date_previously_was, date ].compact.min
end
account.sync_later(sync_start_date)
end
private
def previous_valuation
@previous_valuation ||= self.account
.valuations
.where("date < ?", date)
.order(date: :desc)
.first
end
def create_trend
TimeSeries::Trend.new \
current: self.value,
previous: previous_valuation&.value,
favorable_direction: account.favorable_direction
end
end

View file

@ -1,16 +1,15 @@
class TimeSeries::Trend
include ActiveModel::Validations
attr_reader :current, :previous
delegate :favorable_direction, to: :series
attr_reader :current, :previous, :favorable_direction
validate :values_must_be_of_same_type, :values_must_be_of_known_type
def initialize(current:, previous:, series: nil)
def initialize(current:, previous:, series: nil, favorable_direction: nil)
@current = current
@previous = previous
@series = series
@favorable_direction = get_favorable_direction(favorable_direction)
validate!
end
@ -25,6 +24,17 @@ class TimeSeries::Trend
end.inquiry
end
def color
case direction
when "up"
favorable_direction.down? ? red_hex : green_hex
when "down"
favorable_direction.down? ? green_hex : red_hex
else
gray_hex
end
end
def value
if previous.nil?
current.is_a?(Money) ? Money.new(0) : 0
@ -56,8 +66,21 @@ class TimeSeries::Trend
end
private
attr_reader :series
def red_hex
"#F13636" # red-500
end
def green_hex
"#10A861" # green-600
end
def gray_hex
"#737373" # gray-500
end
def values_must_be_of_same_type
unless current.class == previous.class || [ previous, current ].any?(&:nil?)
errors.add :current, "must be of the same type as previous"
@ -90,4 +113,9 @@ class TimeSeries::Trend
obj
end
end
def get_favorable_direction(favorable_direction)
direction = favorable_direction.presence || series&.favorable_direction
(direction.presence_in(TimeSeries::DIRECTIONS) || "up").inquiry
end
end

View file

@ -1,13 +0,0 @@
class Valuation < ApplicationRecord
include Monetizable
belongs_to :account
validates :account, :date, :value, presence: true
monetize :value
scope :in_period, ->(period) { period.date_range.nil? ? all : where(date: period.date_range) }
def self.to_series
TimeSeries.from_collection all, :value_money
end
end