1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-07-24 15:49:39 +02:00

Plaid portfolio sync algorithm and calculation improvements (#1526)

* Start tests rework

* Cash balance on schema

* Add reverse syncer

* Reverse balance sync with holdings

* Reverse holdings sync

* Reverse holdings sync should work with only trade entries

* Consolidate brokerage cash

* Add forward sync option

* Update new balance info after syncs

* Intraday balance calculator and sync fixes

* Show only balance for trade entries

* Tests passing

* Update Gemfile.lock

* Cleanup, performance improvements

* Remove account reloads for reliable sync outputs

* Simplify valuation view logic

* Special handling for Plaid cash holding
This commit is contained in:
Zach Gollwitzer 2024-12-10 17:41:20 -05:00 committed by GitHub
parent a59ca5b7c6
commit 49c353e10c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
72 changed files with 1152 additions and 1046 deletions

View file

@ -16,7 +16,7 @@ class Account < ApplicationRecord
has_many :balances, dependent: :destroy
has_many :issues, as: :issuable, dependent: :destroy
monetize :balance
monetize :balance, :cash_balance
enum :classification, { asset: "asset", liability: "liability" }, validate: { allow_nil: true }
@ -32,8 +32,6 @@ class Account < ApplicationRecord
accepts_nested_attributes_for :accountable, update_only: true
delegate :value, :series, to: :accountable
class << self
def by_group(period: Period.all, currency: Money.default_currency.iso_code)
grouped_accounts = { assets: ValueGroup.new("Assets", currency), liabilities: ValueGroup.new("Liabilities", currency) }
@ -59,7 +57,7 @@ class Account < ApplicationRecord
def create_and_sync(attributes)
attributes[:accountable_attributes] ||= {} # Ensure accountable is created, even if empty
account = new(attributes)
account = new(attributes.merge(cash_balance: attributes[:balance]))
transaction do
# Create 2 valuations for new accounts to establish a value history for users to see
@ -94,15 +92,27 @@ class Account < ApplicationRecord
def sync_data(start_date: nil)
update!(last_synced_at: Time.current)
resolve_stale_issues
Balance::Syncer.new(self, start_date: start_date).run
Holding::Syncer.new(self, start_date: start_date).run
Syncer.new(self, start_date: start_date).run
end
def post_sync
broadcast_remove_to(family, target: "syncing-notice")
resolve_stale_issues
accountable.post_sync
end
def series(period: Period.last_30_days, currency: nil)
balance_series = balances.in_period(period).where(currency: currency || self.currency)
if balance_series.empty? && period.date_range.end == Date.current
TimeSeries.new([ { date: Date.current, value: balance_money.exchange_to(currency || self.currency) } ])
else
TimeSeries.from_collection(balance_series, :balance_money, favorable_direction: asset? ? "up" : "down")
end
rescue Money::ConversionError
TimeSeries.new([])
end
def original_balance
balance_amount = balances.chronological.first&.balance || balance
Money.new(balance_amount, currency)