1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-08-07 22:45:20 +02:00

Additional cache columns on balances for activity view breakdowns (#2505)

* Initial schema iteration

* Add new balance components

* Add existing data migrator to backfill components

* Update calculator test assertions for new balance components

* Update flow assertions for forward calculator

* Update reverse calculator flows assumptions

* Forward calculator tests passing

* Get all calculator tests passing

* Assert flows factor
This commit is contained in:
Zach Gollwitzer 2025-07-23 10:06:25 -04:00 committed by GitHub
parent 347c0a7906
commit da2045dbd8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 1159 additions and 177 deletions

View file

@ -11,6 +11,8 @@ class Balance::ReverseCalculator < Balance::BaseCalculator
# Calculates in reverse-chronological order (End of day -> Start of day)
account.current_anchor_date.downto(account.opening_anchor_date).map do |date|
flows = flows_for_date(date)
if use_opening_anchor_for_date?(date)
end_cash_balance = derive_cash_balance_on_date_from_total(
total_balance: account.opening_anchor_balance,
@ -20,29 +22,30 @@ class Balance::ReverseCalculator < Balance::BaseCalculator
start_cash_balance = end_cash_balance
start_non_cash_balance = end_non_cash_balance
build_balance(
date: date,
cash_balance: end_cash_balance,
non_cash_balance: end_non_cash_balance
)
market_value_change = 0
else
start_cash_balance = derive_start_cash_balance(end_cash_balance: end_cash_balance, date: date)
start_non_cash_balance = derive_start_non_cash_balance(end_non_cash_balance: end_non_cash_balance, date: date)
# Even though we've just calculated "start" balances, we set today equal to end of day, then use those
# in our next iteration (slightly confusing, but just the nature of a "reverse" sync)
output_balance = build_balance(
date: date,
cash_balance: end_cash_balance,
non_cash_balance: end_non_cash_balance
)
end_cash_balance = start_cash_balance
end_non_cash_balance = start_non_cash_balance
output_balance
market_value_change = market_value_change_on_date(date, flows)
end
output_balance = build_balance(
date: date,
balance: end_cash_balance + end_non_cash_balance,
cash_balance: end_cash_balance,
start_cash_balance: start_cash_balance,
start_non_cash_balance: start_non_cash_balance,
cash_inflows: flows[:cash_inflows],
cash_outflows: flows[:cash_outflows],
non_cash_inflows: flows[:non_cash_inflows],
non_cash_outflows: flows[:non_cash_outflows],
net_market_flows: market_value_change
)
end_cash_balance = start_cash_balance
end_non_cash_balance = start_non_cash_balance
output_balance
end
end
end
@ -58,13 +61,6 @@ class Balance::ReverseCalculator < Balance::BaseCalculator
account.asset? ? entry_flows : -entry_flows
end
# Reverse syncs are a bit different than forward syncs because we do not allow "reconciliation" valuations
# to be used at all. This is primarily to keep the code and the UI easy to understand. For a more detailed
# explanation, see the test suite.
def use_opening_anchor_for_date?(date)
account.has_opening_anchor? && date == account.opening_anchor_date
end
# Alias method, for algorithmic clarity
# Derives cash balance, starting from the end-of-day, applying entries in reverse to get the start-of-day balance
def derive_start_cash_balance(end_cash_balance:, date:)
@ -76,4 +72,11 @@ class Balance::ReverseCalculator < Balance::BaseCalculator
def derive_start_non_cash_balance(end_non_cash_balance:, date:)
derive_non_cash_balance(end_non_cash_balance, date, direction: :reverse)
end
# Reverse syncs are a bit different than forward syncs because we do not allow "reconciliation" valuations
# to be used at all. This is primarily to keep the code and the UI easy to understand. For a more detailed
# explanation, see the test suite.
def use_opening_anchor_for_date?(date)
account.has_opening_anchor? && date == account.opening_anchor_date
end
end