Handle holding quantity generation for reverse syncs correctly when not all holdings are generated for current day #2417

Merged
zachgoll merged 4 commits from zachgoll/maybe-885-maybes-investment-account-graph-holdings-ui-doesnt-properly into main 2025-06-27 04:57:17 +08:00
zachgoll commented 2025-06-27 04:16:48 +08:00 (Migrated from github.com)

The holdings reverse calculation system was broken across multiple components, causing incorrect portfolio generation when holdings existed on different dates. The core issues:

  1. Stale data accumulation: When Plaid provided holdings with institution_price_as_of dates, future holdings in our DB weren't cleaned up per security
  2. Date handling failures: System assumed all holdings shared the same "latest" date, but holdings could exist on different dates (e.g., NVDA from yesterday, AAPL from today)
  3. Poor separation of concerns: Reverse calculator generated its own starting portfolio instead of using actual current holdings
  4. UI pollution: Zero-quantity holdings cluttered the interface

Solution

  • HoldingsProcessor: Delete stale holdings per security after persisting, using institution_price_as_of as authoritative cutoff
  • PortfolioSnapshot: New class to capture most recent holding quantities per security, handling different dates properly
  • Materializer: Pass portfolio snapshot to reverse calculator instead of letting it generate its own starting point
  • ReverseCalculator: Use snapshot directly, always start from "today" regardless of snapshot dates, removed empty_portfolio/generate_starting_portfolio methods
  • Account#current_holdings: Handle different dates with DISTINCT ON and filter out zero quantities from UI

Result

  • Accurate reverse calculation regardless of holding date differences
  • Proper cleanup of stale holdings data per security
  • Clean UI showing only meaningful holdings (cash always visible)
  • Better separation of concerns with comprehensive test coverage
The holdings reverse calculation system was broken across multiple components, causing incorrect portfolio generation when holdings existed on different dates. The core issues: 1. Stale data accumulation: When Plaid provided holdings with institution_price_as_of dates, future holdings in our DB weren't cleaned up per security 2. Date handling failures: System assumed all holdings shared the same "latest" date, but holdings could exist on different dates (e.g., NVDA from yesterday, AAPL from today) 3. Poor separation of concerns: Reverse calculator generated its own starting portfolio instead of using actual current holdings 4. UI pollution: Zero-quantity holdings cluttered the interface Solution - HoldingsProcessor: Delete stale holdings per security after persisting, using institution_price_as_of as authoritative cutoff - PortfolioSnapshot: New class to capture most recent holding quantities per security, handling different dates properly - Materializer: Pass portfolio snapshot to reverse calculator instead of letting it generate its own starting point - ReverseCalculator: Use snapshot directly, always start from "today" regardless of snapshot dates, removed empty_portfolio/generate_starting_portfolio methods - Account#current_holdings: Handle different dates with DISTINCT ON and filter out zero quantities from UI Result - Accurate reverse calculation regardless of holding date differences - Proper cleanup of stale holdings data per security - Clean UI showing only meaningful holdings (cash always visible) - Better separation of concerns with comprehensive test coverage
Sign in to join this conversation.