0.2.36: Investor View carries exit status + grey out fully-exited fund cards
The admin read-only Investor View built capital-account responses without exited_on, so an exited position showed the active card with $0s (the LP's own portal was correct). Extracted exit_dates() into capital_account_router and stamp it in investor_view too; regression test added. A fund card where every position is exited now renders greyed (bg + title) so it reads as closed at a glance. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
2c87ab499a
commit
1deb6586b0
@@ -21,6 +21,22 @@ def _dollars_to_cents(dollars: float) -> int:
|
||||
return round(dollars * 100)
|
||||
|
||||
|
||||
def exit_dates(session: Session, rows) -> dict:
|
||||
"""(investor_user_id, entity_id) -> exited_on for every exited pair in these statements,
|
||||
so a sold/transferred stake renders as "Exited" instead of a phantom -100% loss."""
|
||||
if not rows:
|
||||
return {}
|
||||
return {
|
||||
(a.user_id, a.entity_id): a.exited_on
|
||||
for a in session.exec(
|
||||
select(EntityAccess).where(
|
||||
col(EntityAccess.user_id).in_({r.investor_user_id for r in rows}),
|
||||
col(EntityAccess.exited_on).is_not(None),
|
||||
)
|
||||
).all()
|
||||
}
|
||||
|
||||
|
||||
@router.get("")
|
||||
def list_statements(
|
||||
entity_id: int | None = None,
|
||||
@@ -57,17 +73,7 @@ def list_statements(
|
||||
col(User.id).in_({r.investor_user_id for r in rows})
|
||||
)
|
||||
).all()) if rows else {}
|
||||
# And each (investor, entity)'s exit date, so a sold/transferred stake renders as
|
||||
# "Exited" instead of a phantom -100% loss.
|
||||
exits = {
|
||||
(a.user_id, a.entity_id): a.exited_on
|
||||
for a in session.exec(
|
||||
select(EntityAccess).where(
|
||||
col(EntityAccess.user_id).in_({r.investor_user_id for r in rows}),
|
||||
col(EntityAccess.exited_on).is_not(None),
|
||||
)
|
||||
).all()
|
||||
} if rows else {}
|
||||
exits = exit_dates(session, rows)
|
||||
out: list[CapitalAccountResponse] = []
|
||||
for r in rows:
|
||||
data = CapitalAccountResponse.model_validate(r, from_attributes=True)
|
||||
|
||||
@@ -144,9 +144,14 @@ def investor_view(
|
||||
col(User.id).in_({r.investor_user_id for r in cap_rows})
|
||||
)
|
||||
).all()) if cap_rows else {}
|
||||
# Mirror the investor's own portal exactly — including exit status, so an exited
|
||||
# position shows its badge here too instead of a phantom -100%.
|
||||
from ten31portal.routers.capital_account_router import exit_dates
|
||||
exits = exit_dates(session, cap_rows)
|
||||
for r in cap_rows:
|
||||
d = CapitalAccountResponse.model_validate(r, from_attributes=True)
|
||||
d.investor_name = names.get(r.investor_user_id)
|
||||
d.exited_on = exits.get((r.investor_user_id, r.entity_id))
|
||||
caps.append(d)
|
||||
|
||||
doc_rows = session.exec(
|
||||
|
||||
Reference in New Issue
Block a user