Output:
Chunk ID: 54d224
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1723
Output:
        return {"as_of": as_of, "data_cutoff": cutoff, "base_currency": "CHF", "status": "unavailable", "reason_codes": ["missing_account_valuation"], "tolerance": {"version": TOLERANCE_VERSION, "absolute": str(absolute), "relative": str(relative)}, "coverage": empty_coverage, "differences": [], "account_totals": [], "input_fingerprint": _hash([as_of, cutoff, []]), "sources": [], "limit": limit, "offset": offset, "total": 0}
    placeholders = ",".join("?" for _ in account_map)
    transaction_rows = conn.execute(
        f"""SELECT * FROM transactions WHERE account_id IN ({placeholders}) AND trade_date<=?
            AND datetime(created_at)<=datetime(?)
            AND COALESCE(is_voided,0)=0 AND COALESCE(is_confirmed,1)=1
            ORDER BY trade_date, created_at, transaction_id""", (*account_map, as_of, cutoff)
    ).fetchall()
    quantities: dict[tuple[str, str], Decimal] = {}
    activity_supported = 0
    cost_basis_keys: set[tuple[str, str]] = set()
    for row in transaction_rows:
        kind = str(row["activity_kind"] or row["transaction_type"] or "").lower()
        if kind in SUPPORTED_ACTIVITIES:
            activity_supported += 1
        if not row["instrument_id"] or row["quantity"] in (None, ""):
            continue
        key = (str(row["account_id"]), str(row["instrument_id"]))
        try:
            quantity = _stored_decimal(row["quantity"], "Menge", non_negative=True)
        except ValueError:
            continue
        if kind in {"buy", "initial_position_snapshot"}:
            quantities[key] = quantities.get(key, Decimal("0")) + quantity
            if row["gross_amount_original"] not in (None, ""):
                cost_basis_keys.add(key)
        elif kind in {"partial_sell", "full_sell", "sell"}:
            quantities[key] = quantities.get(key, Decimal("0")) - quantity
    reported_rows = conn.execute(
        f"""WITH ranked AS (
              SELECT p.*, ROW_NUMBER() OVER(PARTITION BY account_id,instrument_id ORDER BY snapshot_date DESC,created_at DESC,position_snapshot_id DESC) rn
              FROM positions_snapshot p WHERE account_id IN ({placeholders}) AND snapshot_date<=?
                AND datetime(created_at)<=datetime(?)
            ) SELECT * FROM ranked WHERE rn=1""", (*account_map, as_of, cutoff)
    ).fetchall()
    reported = {(str(row["account_id"]), str(row["instrument_id"])): row for row in reported_rows}
    keys = sorted(set(quantities) | set(reported))
    differences: list[dict[str, Any]] = []
    price_covered = fx_covered = recon_covered = 0
    account_position_values: dict[str, Decimal] = {key: Decimal("0") for key in account_map}
    account_position_dates: dict[str, set[str]] = {key: set() for key in account_map}
    for account, instrument in keys:
        ledger_qty = quantities.get((account, instrument))
        source = reported.get((account, instrument))
        source_qty = _stored_decimal(source["quantity"], "Gemeldete Menge") if source and source["quantity"] not in (None, "") else None
        reasons: list[str] = []
        if source and str(source["snapshot_date"]) != as_of:
            reasons.append("stale_snapshot")
        if source and str(source["data_quality_status"] or "").lower() not in {"ok", "fresh", "complete"}:
            reasons.append("source_error")
        quantity_status = "unavailable"
        quantity_diff: Decimal | None = None
        if ledger_qty is None or source_qty is None:
            reasons.append("missing_position_snapshot")
        else:
            quantity_diff = ledger_qty - source_qty
            if source and str(source["snapshot_date"]) != as_of:
                quantity_status = "not_comparable"
            else:
                quantity_status = _status(quantity_diff, source_qty, absolute, relative)
                if quantity_status == "mismatch":
                    reasons.append("quantity_mismatch")
        derived_value: Decimal | None = None
        reported_value = _stored_decimal(source["market_value_chf"], "Gemeldeter Positionswert") if source and source["market_value_chf"] not in (None, "") else None
        price_row = conn.execute(
            """SELECT close,currency,price_date,provider FROM market_prices WHERE instrument_id=? AND price_date<=?
               AND datetime(created_at)<=datetime(?)
               AND quality_status IN ('ok','fresh','complete') ORDER BY price_date DESC,created_at DESC,market_price_id DESC LIMIT 1""", (instrument, as_of, cutoff)
        ).fetchone()
        price_date = str(price_row["price_date"]) if price_row else None
        price_source = str(price_row["provider"]) if price_row else None
        fx_date = fx_source = None
        if source and price_row and str(source["snapshot_date"]) != price_date:
            reasons.append("cutoff_mismatch")
        if ledger_qty is None:
            reasons.append("missing_position_snapshot")
        elif not price_row:
            reasons.append("missing_price")
        else:
            if price_date != as_of:
                reasons.append("stale_price")
            else:
                price_covered += 1
            price = _stored_decimal(price_row["close"], "Marktpreis", non_negative=True)
            fx, fx_date, fx_source = _latest_fx(conn, str(price_row["currency"]).upper(), as_of, cutoff)
            if fx is None:
                reasons.append("missing_fx")
            else:
                if fx_date != as_of:
                    reasons.append("stale_fx")
                else:
                    fx_covered += 1
                derived_value = ledger_qty * price * fx
        value_status = "unavailable"
        value_diff: Decimal | None = None
        relative_diff: Decimal | None = None
        if derived_value is not None and reported_value is not None:
            if source and (
                "cutoff_mismatch" in reasons
                or "stale_snapshot" in reasons
                or "stale_price" in reasons
                or "stale_fx" in reasons
                or (fx_date and fx_date != price_date)
            ):
                value_status = "not_comparable"
                if "cutoff_mismatch" not in reasons:
                    reasons.append("cutoff_mismatch")
            else:
                value_diff = derived_value - reported_value
                relative_diff = value_diff / reported_value if reported_value != 0 else None
                value_status = _status(value_diff, reported_value, absolute, relative)
                if value_status == "mismatch":
                    reasons.append("value_mismatch")
                recon_covered += 1
        elif reported_value is None:
            reasons.append("missing_position_snapshot")
        if source and reported_value is not None:
            account_position_values[account] += reported_value
            account_position_dates[account].add(str(source["snapshot_date"]))


grep -n "def get_command_center_summary" -A80 src/jarvis_finance/dashboard/data.py


Output:
Chunk ID: 2f18c9
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 807
Output:
1170:def get_command_center_summary(conn: Connection) -> dict[str, str]:
1171-    cash_rows = get_cash_overview(conn)
1172-    crypto_summary = get_crypto_summary_cards(conn)
1173-    positions = [r for r in get_positions(conn) if r.get("asset_class", "").lower() in {"stock", "equity", "etf"} and r.get("instrument_status", "").lower() != "inactive"]
1174-    cash_total = sum(d(r["amount_chf"]) for r in cash_rows if r["amount_chf"])
1175-    crypto_total = d(crypto_summary["total_value_chf"])
1176-    stock_rows = [r for r in positions if r.get("asset_class", "").lower() in {"stock", "equity"}]
1177-    etf_rows = [r for r in positions if r.get("asset_class", "").lower() == "etf"]
1178-    stock_total = sum(d(r["market_value_chf"]) for r in stock_rows if r.get("market_value_chf"))
1179-    etf_total = sum(d(r["market_value_chf"]) for r in etf_rows if r.get("market_value_chf"))
1180-    equity_total = stock_total + etf_total
1181-    missing_price_count = sum(1 for r in positions if not r.get("market_price_original"))
1182-    missing_fx_count = sum(1 for r in positions if r.get("fx_status") == "missing_fx")
1183-    incomplete_cost_count = sum(1 for r in positions if "cost_basis_uncertain" in (r.get("quality_warnings") or "") or not r.get("cost_basis_chf"))
1184-    unvalued_count = missing_price_count + missing_fx_count
1185-    latest_equity_price = max((r.get("price_date") or "" for r in positions), default="")
1186-    alert_counts = conn.execute("SELECT priority, COUNT(*) AS c FROM alerts WHERE status='active' GROUP BY priority").fetchall()
1187-    critical = sum(int(r["c"] or 0) for r in alert_counts if r["priority"] == "kritisch")
1188-    quality = get_data_quality(conn)
1189-    dq = "kritisch" if any(i["severity"] == "kritisch" and i["count"] != "0" for i in quality) else ("warnung" if any(i["severity"] == "warnung" and i["count"] != "0" for i in quality) else "ok")
1190-    total = cash_total + crypto_total + equity_total
1191-    return {
1192-        "base_currency": "CHF",
1193-        "cash_total_chf": dec_text(cash_total, "0.01"),
1194-        "crypto_total_chf": dec_text(crypto_total, "0.01"),
1195-        "stock_total_chf": dec_text(stock_total, "0.01"),
1196-        "etf_total_chf": dec_text(etf_total, "0.01"),
1197-        "equity_etf_total_chf": dec_text(equity_total, "0.01"),
1198-        "equity_position_count": str(len(positions)),
1199-        "unvalued_position_count": str(unvalued_count),
1200-        "missing_price_count": str(missing_price_count),
1201-        "missing_fx_count": str(missing_fx_count),
1202-        "incomplete_cost_count": str(incomplete_cost_count),
1203-        "total_portfolio_chf": dec_text(total, "0.01"),
1204-        "total_value_chf": dec_text(total, "0.01"),
1205-        "critical_alert_count": str(critical),
1206-        "active_alerts": ", ".join(f"{r['priority']}: {r['c']}" for r in alert_counts) or "0",
1207-        "data_quality_status": dq,
1208-        "last_price_update_at": max([crypto_summary.get("last_price_update_at", ""), latest_equity_price]),
1209-        "crypto_price_data_as_of": crypto_summary.get("last_price_update_at", ""),
1210-        "equity_price_data_as_of": latest_equity_price,
1211-    }


nl -ba src/jarvis_finance/services/cash_service.py | sed -n '300,345p'


Output:
Chunk ID: 72a762
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 651
Output:
   300	            for currency in sorted(set(components) | set(deltas)):
   301	                component = components.get(currency)
   302	                delta_original, delta_chf = deltas.get(
   303	                    currency,
   304	                    (Decimal("0"), Decimal("0")),
   305	                )
   306	                amount_original = (
   307	                    component.amount_original if component else Decimal("0")
   308	                ) + delta_original
   309	                baseline_chf = component.amount_chf if component else Decimal("0")
   310	                amount_chf = (
   311	                    baseline_chf + delta_chf if delta_chf is not None else baseline_chf
   312	                )
   313	                status = (
   314	                    "Abgleich offen"
   315	                    if delta_chf is None
   316	                    else "Offiziell abgeglichen + Bewegungen"
   317	                    if delta_original or delta_chf
   318	                    else "Offiziell abgeglichen"
   319	                )
   320	                positions.append(
   321	                    CashPosition(
   322	                        id=f"{account_id}:{currency}",
   323	                        account_id=account_id,
   324	                        platform=row["platform"],
   325	                        account_label=row["account_name"],
   326	                        account_type=row["account_type"],
   327	                        currency=currency,
   328	                        balance_mode="official_components",
   329	                        amount=decimal_text(amount_original, 2),
   330	                        amount_chf=decimal_text(amount_chf, 2),
   331	                        calculated_balance_chf=decimal_text(amount_chf, 2),
   332	                        manual_balance_chf=None,
   333	                        csv_anchor_balance_chf=None,
   334	                        used_value_chf=decimal_text(amount_chf, 2),
   335	                        difference_chf="0.00",
   336	                        last_manual_reconciliation=snapshot_date,
   337	                        last_imported_booking=_last_imported_booking(conn, account_id),
   338	                        status=status,
   339	                    )
   340	                )
   341	            continue
   342	        manual = _latest_snapshot(conn, account_id, "manual_balance")
   343	        anchor = _latest_snapshot(conn, account_id, "csv_anchor_balance")
   344	        mode = row["balance_mode"] or "manual"
   345	        default_currency = str(row["currency"])


nl -ba src/jarvis_finance/services/cash_service.py | sed -n '345,390p'


Output:
Chunk ID: ab6d6c
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 568
Output:
   345	        default_currency = str(row["currency"])
   346	        ledger_currencies = {
   347	            currency
   348	            for ledger_account_id, currency in ledger.balances
   349	            if ledger_account_id == account_id
   350	        }
   351	        # Manual balances and CSV anchors are account-level CHF controls. They must
   352	        # not be added to per-currency ledger rows from the same account.
   353	        currencies = (
   354	            {default_currency}
   355	            if manual or anchor
   356	            else set(ledger_currencies) or {default_currency}
   357	        )
   358	        for currency in sorted(currencies):
   359	            ledger_balance = ledger.balances.get((account_id, currency))
   360	            if manual or anchor:
   361	                calculated = _calculated_balance(conn, account_id)
   362	                amount_original = (
   363	                    calculated if currency.upper() == "CHF" else Decimal("0")
   364	                )
   365	            elif ledger_balance is not None:
   366	                calculated = ledger_balance.amount_chf or Decimal("0")
   367	                amount_original = ledger_balance.amount_original
   368	            else:
   369	                calculated = _calculated_balance(conn, account_id)
   370	                amount_original = (
   371	                    calculated if currency.upper() == "CHF" else Decimal("0")
   372	                )
   373	            manual_amount = (
   374	                Decimal(str(manual["amount_chf"]))
   375	                if manual and currency == default_currency
   376	                else None
   377	            )
   378	            used = (
   379	                manual_amount
   380	                if mode == "manual" and manual_amount is not None
   381	                else calculated
   382	            )
   383	            difference = (
   384	                manual_amount - calculated
   385	                if manual_amount is not None
   386	                else Decimal("0")
   387	            )
   388	            status = "Abgleich offen" if manual_amount is not None and difference != 0 else "Aktuell"
   389	            positions.append(
   390	                CashPosition(


[P2] Include cash balance currencies in the cash read model

When a cash account has materialized `cash_balances` rows but no transaction-ledger balance for that currency, this only iterates `ledger_currencies` and falls back to the account default currency. For example, a USD sale/dividend posting written to `cash_balances` on a CHF cash account is now exposed by `get_cash_overview()` as a CHF amount (or omitted if another ledger currency exists), which misstates both original currency and amount in the shared cash/dashboard read model.

The shared cash read model can mislabel or omit non-default-currency cash balances that are stored in `cash_balances`, which affects dashboard/API totals and position details for common sale/dividend postings.