PYTHONDONTWRITEBYTECODE=1 python - <<'PY'
from tests.test_truewealth_sprint12 import make_conn, statement, confirm_import, import_request
from jarvis_finance.services import truewealth_service as service
conn=make_conn(); raw=b'%PDF-x'; service.parse_truewealth_tax_statement=lambda value: statement(value); service._archive_pdf=lambda raw,digest: (f'truewealth/archive/{digest}.pdf', False)
confirm_import(conn, raw)
payload={"total_value_chf":"12500", "valuation_at":"2026-07-28T08:00:00Z", "note":"portal"}
preview=service.preview_manual_truewealth_value(conn,payload)
res=service.confirm_manual_truewealth_value(conn,{**payload,**{k:preview[k] for k in ('preview_id','confirmation_id')},'confirm':True})
print(service.get_truewealth_summary(conn)['current_value_chf'])
print(service.set_manual_truewealth_value_active(conn,res['snapshot_id'], {'active':False,'note':'x','confirm':True}))
print(service.get_truewealth_summary(conn)['current_value_chf'])
PY


Output:
Chunk ID: 2cce76
Wall time: 0.0346 seconds
Process exited with code 0
Original token count: 38
Output:
12500.00
{'status': 'confirmed', 'snapshot_id': 'acctval_71f2a2e0635c406594e6', 'audit_id': 'audit_48e32087973440c18700', 'idempotent': False}
12000.00


nl -ba src/jarvis_finance/services/truewealth_service.py | sed -n '585,630p'


Output:
Chunk ID: f0cae9
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 790
Output:
   585	    official = conn.execute(
   586	        """SELECT * FROM truewealth_snapshots
   587	           WHERE account_id=? ORDER BY snapshot_date DESC,created_at DESC LIMIT 1""",
   588	        (account_id,),
   589	    ).fetchone()
   590	    positions: list[dict[str, Any]] = []
   591	    cash: list[dict[str, Any]] = []
   592	    if official:
   593	        positions = [dict(row) for row in conn.execute(
   594	            """SELECT snapshot_position_id,instrument_name,isin,asset_type,quantity,price_currency,
   595	                      source_price,source_value_chf
   596	               FROM truewealth_snapshot_positions WHERE snapshot_id=? ORDER BY instrument_name""",
   597	            (official["snapshot_id"],),
   598	        ).fetchall()]
   599	        cash = [dict(row) for row in conn.execute(
   600	            """SELECT snapshot_cash_id,currency,amount_original,fx_rate_to_chf,source_value_chf
   601	               FROM truewealth_snapshot_cash WHERE snapshot_id=? ORDER BY currency""",
   602	            (official["snapshot_id"],),
   603	        ).fetchall()]
   604	    history = [dict(row) for row in conn.execute(
   605	        """SELECT snapshot_id,total_value_chf,valuation_date,
   606	                  COALESCE(valuation_at,valuation_date || 'T23:59:58Z') AS valuation_at,
   607	                  source_type,quality_status,notes,COALESCE(is_active,1) AS is_active,deactivated_at,deactivation_reason
   608	           FROM account_value_snapshots WHERE account_id=?
   609	           ORDER BY valuation_date DESC,COALESCE(valuation_at,created_at) DESC,created_at DESC""",
   610	        (account_id,),
   611	    ).fetchall()]
   612	    imports = [dict(row) for row in conn.execute(
   613	        """SELECT b.batch_id,b.snapshot_date,b.parser_id,b.parser_version,b.confirmed_at,b.status,
   614	                  s.snapshot_id,s.position_count,s.cash_count,s.source_total_chf,s.securities_total_chf,
   615	                  s.cash_total_chf,s.components_total_chf,s.reconciliation_difference_chf,s.reconciliation_status,
   616	                  s.completeness_status
   617	           FROM truewealth_import_batches b JOIN truewealth_snapshots s ON s.batch_id=b.batch_id
   618	           WHERE b.account_id=? ORDER BY b.snapshot_date DESC,b.confirmed_at DESC""",
   619	        (account_id,),
   620	    ).fetchall()]
   621	    current_type = str(current["source_type"]) if current else "unavailable"
   622	    current_is_manual = current_type == "truewealth_manual_provisional"
   623	    return {
   624	        "portfolio_label": TRUEWEALTH_LABEL,
   625	        "current_value_chf": str(current["total_value_chf"]) if current else None,
   626	        "current_valuation_at": str(current["valuation_at"]) if current else None,
   627	        "current_source_type": current_type,
   628	        "current_is_manual_provisional": current_is_manual,
   629	        "current_label": f"Gesamtwert manuell aktualisiert am {current['valuation_at']}" if current_is_manual else "Gesamtwert gemäss offiziellem Import",
   630	        "positions_snapshot_date": str(official["snapshot_date"]) if official else None,


[P2] Treat legacy manual values as manual, not official

When the latest TrueWealth account value is an existing `manual_total_value` row from the previous manual workflow, `current_is_manual` is false, so the summary labels it as `Gesamtwert gemäss offiziellem Import` and suppresses the manual/mixed-date warnings. This can present unverified legacy manual data as an official import until a new `truewealth_*` snapshot supersedes it; only `truewealth_official_import` should get the official label/semantics.

The patch can misclassify legacy manual TrueWealth valuations as official imported values in the new summary API, which undermines the verified-source separation this change introduces.