1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-08-06 14:05:20 +02:00
Maybe/app/models/holding/portfolio_snapshot.rb
Zach Gollwitzer 8db95623cf
Handle holding quantity generation for reverse syncs correctly when not all holdings are generated for current day (#2417)
* Handle reverse calculator starting portfolio generation correctly

* Fix current_holdings to handle different dates and hide zero quantities

- Use DISTINCT ON to get most recent holding per security instead of assuming same date
- Filter out zero quantity holdings from UI display
- Maintain cash display regardless of zero balance
- Use single efficient query with proper Rails syntax

* Continue to process holdings even if one is not resolvable

* Lint fixes
2025-06-26 16:57:17 -04:00

32 lines
1 KiB
Ruby

# Captures the most recent holding quantities for each security in an account's portfolio.
# Returns a portfolio hash compatible with the reverse calculator's format.
class Holding::PortfolioSnapshot
attr_reader :account
def initialize(account)
@account = account
end
# Returns a hash of {security_id => qty} representing today's starting portfolio.
# Includes all securities from trades (with 0 qty if no holdings exist).
def to_h
@portfolio ||= build_portfolio
end
private
def build_portfolio
# Start with all securities from trades initialized to 0
portfolio = account.trades
.pluck(:security_id)
.uniq
.each_with_object({}) { |security_id, hash| hash[security_id] = 0 }
# Get the most recent holding for each security and update quantities
account.holdings
.select("DISTINCT ON (security_id) security_id, qty")
.order(:security_id, date: :desc)
.each { |holding| portfolio[holding.security_id] = holding.qty }
portfolio
end
end