fidelity: push per-fund manual snapshot instead of gains-offset DEPOSIT
PlanViewer's DisplayValuation.action JSON already gives us current fund units + unit price; we were parsing it and throwing it away, emitting only a single 'unrealised-gains-offset' DEPOSIT to make Wealthfolio's totals match the dashboard. That hack double-counted the gain as a cash contribution, hiding £35k of pension growth from every contribution/growth/ROI panel. New flow: - FidelityPlanViewerProvider exposes last_holdings + last_total_contribution after fetch() drains. - fidelity-ingest CLI converts to a ManualSnapshotPayload (cost basis allocated proportionally by current fund value share) and posts to WF /api/v1/snapshots/import. WF auto-creates unknown fund symbols with kind=INVESTMENT, quoteMode=MANUAL, quoteCcy=GBP. - The gains-offset emission is removed entirely. Historical offset rows already in WF are corrected at the dashboard layer by the dav_corrected view shipped in infra@2841347e. WealthfolioSink gains push_manual_snapshots() + ManualSnapshotPayload / SnapshotPosition wire types. 11 sink tests (3 new) + 9 fidelity provider tests (2 changed, 1 new) all green; mypy + ruff clean.
This commit is contained in:
parent
5adc4a7ba4
commit
cb159e17d9
5 changed files with 339 additions and 60 deletions
|
|
@ -438,6 +438,15 @@ def fidelity_ingest(
|
|||
sys.exit(2)
|
||||
|
||||
async def _run() -> None:
|
||||
from datetime import date as _date_t
|
||||
|
||||
from broker_sync.providers.fidelity_planviewer import (
|
||||
ACCOUNT_ID as FID_ACCOUNT_ID,
|
||||
)
|
||||
from broker_sync.providers.fidelity_planviewer import (
|
||||
fidelity_holdings_to_snapshot,
|
||||
)
|
||||
|
||||
sink = WealthfolioSink(
|
||||
base_url=wf_base_url,
|
||||
username=wf_username,
|
||||
|
|
@ -455,12 +464,31 @@ def fidelity_ingest(
|
|||
result = await sync_provider_to_wealthfolio(
|
||||
provider=provider, sink=sink, dedup=dedup, since=since,
|
||||
)
|
||||
# PlanViewer has no historical per-fund unit-price feed, so
|
||||
# the Activity stream above only carries cash flows. The
|
||||
# current-pot fund positions captured in the same scrape get
|
||||
# pushed via /api/v1/snapshots/import so per-fund quantity +
|
||||
# cost basis land in WF (and propagate to the wealth
|
||||
# dashboard's Positions table via pg-sync).
|
||||
snapshot_imported = 0
|
||||
if provider.last_holdings:
|
||||
snapshot = fidelity_holdings_to_snapshot(
|
||||
holdings=provider.last_holdings,
|
||||
total_real_contribution=provider.last_total_contribution,
|
||||
as_of=_date_t.today(),
|
||||
)
|
||||
if snapshot is not None:
|
||||
push_result = await sink.push_manual_snapshots(
|
||||
account_id=FID_ACCOUNT_ID, snapshots=[snapshot],
|
||||
)
|
||||
snapshot_imported = int(push_result.get("snapshotsImported", 0))
|
||||
finally:
|
||||
await sink.close()
|
||||
typer.echo(f"fidelity-ingest: fetched={result.fetched} "
|
||||
f"new={result.new_after_dedup} "
|
||||
f"imported={result.imported} "
|
||||
f"failed={result.failed}")
|
||||
f"failed={result.failed} "
|
||||
f"snapshots={snapshot_imported}")
|
||||
if result.failed > 0:
|
||||
sys.exit(1)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue