06/03 Optimize codes, Schwab account
This commit is contained in:
@@ -324,8 +324,16 @@ def update_prices(investment_ids=None):
|
||||
|
||||
|
||||
def get_portfolio_summary():
|
||||
"""Return portfolio-level aggregates across all active investments."""
|
||||
investments = Investment.query.filter_by(is_active=True).all()
|
||||
"""
|
||||
Return portfolio-level aggregates across all active investments.
|
||||
Also returns per-account groups for investments that are linked to an account
|
||||
(e.g. separate Schwab Individual vs Roth IRA views).
|
||||
"""
|
||||
investments = Investment.query.filter_by(is_active=True).order_by(
|
||||
Investment.account_id.asc().nullslast(),
|
||||
Investment.asset_type,
|
||||
Investment.asset_name,
|
||||
).all()
|
||||
|
||||
total_cost = sum(i.total_cost for i in investments)
|
||||
total_value = sum(i.current_value for i in investments)
|
||||
@@ -348,6 +356,31 @@ def get_portfolio_summary():
|
||||
'color': ASSET_COLORS.get(asset_type, '#94a3b8'),
|
||||
})
|
||||
|
||||
# Build per-account groups (only for investments with account_id set)
|
||||
account_groups = {} # account_id (or None) → {'account': Account|None, 'investments': [...]}
|
||||
for inv in investments:
|
||||
key = inv.account_id
|
||||
if key not in account_groups:
|
||||
account_groups[key] = {
|
||||
'account': inv.account, # Account object or None
|
||||
'investments': [],
|
||||
'total_value': 0,
|
||||
'total_cost': 0,
|
||||
}
|
||||
account_groups[key]['investments'].append(inv)
|
||||
account_groups[key]['total_value'] += inv.current_value
|
||||
account_groups[key]['total_cost'] += inv.total_cost
|
||||
|
||||
# Sort: named accounts first (sorted by name), then unlinked holdings last
|
||||
sorted_groups = sorted(
|
||||
account_groups.values(),
|
||||
key=lambda g: (g['account'] is None, g['account'].name if g['account'] else ''),
|
||||
)
|
||||
|
||||
# Only return groups if there's more than one distinct account present
|
||||
multi_account = len([g for g in sorted_groups if g['account'] is not None]) > 1 or \
|
||||
(len(sorted_groups) > 1)
|
||||
|
||||
return {
|
||||
'investments': investments,
|
||||
'total_cost': total_cost,
|
||||
@@ -356,4 +389,5 @@ def get_portfolio_summary():
|
||||
'total_gain_pct': total_gain_pct,
|
||||
'allocation': allocation,
|
||||
'count': len(investments),
|
||||
'account_groups': sorted_groups if multi_account else [],
|
||||
}
|
||||
|
||||
@@ -264,7 +264,13 @@ def sync_account_snapshot(schwab_account):
|
||||
market_value = float(pos.get('marketValue') or 0)
|
||||
cur_price = round(market_value / long_qty, 4) if long_qty > 0 else avg_price
|
||||
|
||||
inv = Investment.query.filter_by(ticker=symbol, is_active=True).first()
|
||||
pfm_acct_id = schwab_account.pfm_account_id
|
||||
|
||||
# Match on (ticker, account_id) so the same ticker in different accounts
|
||||
# (e.g. AAPL in Individual vs Roth IRA) remains separate.
|
||||
inv = Investment.query.filter_by(
|
||||
ticker=symbol, account_id=pfm_acct_id, is_active=True
|
||||
).first()
|
||||
if inv:
|
||||
inv.shares = long_qty
|
||||
if avg_price > 0:
|
||||
@@ -274,6 +280,7 @@ def sync_account_snapshot(schwab_account):
|
||||
else:
|
||||
name = (instrument.get('description') or symbol).strip()
|
||||
inv = Investment(
|
||||
account_id = pfm_acct_id,
|
||||
asset_name = name,
|
||||
ticker = symbol,
|
||||
asset_type = pfm_type,
|
||||
|
||||
Reference in New Issue
Block a user