Output:
Chunk ID: 7ea571
Wall time: 0.8565 seconds
Process exited with code 0
Original token count: 9098
Output:
grep: ./src/jarvis_finance/storage/__pycache__/postfinance_schema.cpython-311.pyc: binary file matches
grep: ./src/jarvis_finance/dashboard/__pycache__/data.cpython-312.pyc: binary file matches
grep: ./src/jarvis_finance/dashboard/__pycache__/data.cpython-311.pyc: binary file matches
grep: ./src/jarvis_finance/services/__pycache__/postfinance_service.cpython-311.pyc: binary file matches
grep: ./src/jarvis_finance/services/__pycache__/portfolio_data.cpython-311.pyc: binary file matches
grep: ./src/jarvis_finance/services/__pycache__/cash_service.cpython-311.pyc: binary file matches
grep: ./src/jarvis_finance/services/__pycache__/portfolio_aggregation.cpython-311.pyc: binary file matches
grep: ./src/jarvis_finance/services/__pycache__/portfolio_analytics.cpython-312.pyc: binary file matches
grep: ./src/jarvis_finance/services/__pycache__/portfolio_aggregation.cpython-312.pyc: binary file matches
grep: ./src/jarvis_finance/services/__pycache__/portfolio_analytics.cpython-311.pyc: binary file matches
grep: ./src/jarvis_finance/services/__pycache__/postfinance_service.cpython-312.pyc: binary file matches
grep: ./tests/__pycache__/test_postfinance_sprint13.cpython-311-pytest-9.1.1.pyc: binary file matches
grep: ./tests/__pycache__/test_postfinance_sprint13.cpython-311.pyc: binary file matches
grep: ./tests/__pycache__/test_postfinance_sprint13.cpython-311-pytest-9.0.2.pyc: binary file matches
./src/jarvis_finance/storage/postfinance_schema.py:15:        CREATE TABLE IF NOT EXISTS postfinance_account_roles (
./src/jarvis_finance/dashboard/data.py:16:    postfinance_account_roles,
./src/jarvis_finance/dashboard/data.py:564:    roles = postfinance_account_roles(conn)
./src/jarvis_finance/services/portfolio_aggregation.py:65:def postfinance_account_roles(conn: Connection) -> dict[str, str]:
./src/jarvis_finance/services/portfolio_aggregation.py:71:            "SELECT role,account_id FROM postfinance_account_roles ORDER BY role"
./src/jarvis_finance/services/portfolio_aggregation.py:100:    roles = postfinance_account_roles(conn)
./src/jarvis_finance/services/portfolio_aggregation.py:153:    roles = postfinance_account_roles(conn)
./src/jarvis_finance/services/portfolio_aggregation.py:223:    roles = postfinance_account_roles(conn)
./src/jarvis_finance/services/portfolio_data.py:34:    postfinance_account_roles,
./src/jarvis_finance/services/portfolio_data.py:1599:    pf_roles = postfinance_account_roles(conn)
./src/jarvis_finance/services/portfolio_analytics.py:31:    postfinance_account_roles,
./src/jarvis_finance/services/portfolio_analytics.py:238:    trading_cash_id = postfinance_account_roles(conn).get("etrading_cash")
./src/jarvis_finance/services/postfinance_service.py:541:                "INSERT OR IGNORE INTO postfinance_account_roles(role,account_id,source_reference_hash,created_at) VALUES(?,?,NULL,?)",
./src/jarvis_finance/services/postfinance_service.py:545:                "SELECT account_id FROM postfinance_account_roles WHERE role=?", (role,)
./src/jarvis_finance/services/cash_service.py:225:                  SELECT account_id FROM postfinance_account_roles
./tests/test_postfinance_sprint13.py:283:    assert conn.execute("SELECT COUNT(*) FROM postfinance_account_roles").fetchone()[0] == 3
./tests/test_postfinance_sprint13.py:284:    roles = dict(conn.execute("SELECT role,account_id FROM postfinance_account_roles"))
grep: src/jarvis_finance/crypto/__pycache__/transactions.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/ledger/__pycache__/cash.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/imports/__pycache__/execution.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/imports/__pycache__/transactions_importer.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/imports/__pycache__/postfinance_etrading.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/imports/__pycache__/cash_balances_importer.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/imports/__pycache__/crypto_transactions_importer.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/storage/__pycache__/migrations.cpython-311.pyc: binary file matches
src/jarvis_finance/crypto/transactions.py:78:            price_original, currency_original, gross_amount_original, fee_quantity,
src/jarvis_finance/crypto/transactions.py:79:            fee_original, fee_currency, fx_rate_to_chf, amount_chf, from_wallet_id,
src/jarvis_finance/crypto/transactions.py:119:            fee_original, net_amount_original, currency_original, fx_rate_to_chf, fx_status,
src/jarvis_finance/crypto/transactions.py:120:            gross_amount_chf, fee_chf, net_amount_chf, source_type, source_id,
src/jarvis_finance/ledger/cash.py:17:    amount_chf: Decimal | None = Decimal("0")
src/jarvis_finance/ledger/cash.py:78:        ORDER BY account_id, currency_original, trade_date, created_at, transaction_id
src/jarvis_finance/ledger/cash.py:84:        currency = row["currency_original"]
src/jarvis_finance/ledger/cash.py:90:            balance.amount_chf = None
src/jarvis_finance/ledger/cash.py:92:        elif balance.amount_chf is not None:
src/jarvis_finance/ledger/cash.py:93:            balance.amount_chf += chf
src/jarvis_finance/ledger/cash.py:133:            net_amount_original, currency_original, fx_rate_to_chf, fx_status,
src/jarvis_finance/ledger/cash.py:134:            gross_amount_chf, net_amount_chf, source_type, is_confirmed,
src/jarvis_finance/imports/execution.py:40:    required = ["account_id", "instrument_id", "trade_date", "quantity", "currency_original"]
src/jarvis_finance/imports/execution.py:52:          currency_original, fx_rate_to_chf, fx_source, fx_status, gross_amount_chf, fee_chf, tax_chf, net_amount_chf,
src/jarvis_finance/imports/execution.py:59:            payload.get("currency_original"), payload.get("fx_rate_to_chf"), payload.get("fx_source") or "missing_in_source", payload.get("fx_status", "missing"), payload.get("gross_amount_chf"), None, None, None,
src/jarvis_finance/imports/crypto_transactions_importer.py:54:            elif tx=='buy': record_crypto_buy(conn,account_id=account(conn,require_text(row,'account_name',line)),asset_id=aid,to_wallet_id=wallet(conn,require_text(row,'to_wallet_name',line)),quantity=qty,gross_amount_original=dec(row.get('gross_amount_original'),line,'gross_amount_original'),fee_original=feeo,fee_currency=clean(row.get('fee_currency')) or None,currency=require_text(row,'currency_original',line),fx_rate_to_chf=fx,note=note)
src/jarvis_finance/imports/crypto_transactions_importer.py:55:            elif tx=='sell': record_crypto_sell(conn,account_id=account(conn,require_text(row,'account_name',line)),asset_id=aid,from_wallet_id=wallet(conn,require_text(row,'from_wallet_name',line)),quantity=qty,gross_amount_original=dec(row.get('gross_amount_original'),line,'gross_amount_original'),fee_original=feeo,fee_currency=clean(row.get('fee_currency')) or None,currency=require_text(row,'currency_original',line),fx_rate_to_chf=fx,note=note)
src/jarvis_finance/imports/transactions_importer.py:20:    "currency_original",
src/jarvis_finance/imports/transactions_importer.py:83:    currency = require_text(row, "currency_original", line).upper()
src/jarvis_finance/imports/transactions_importer.py:116:        "currency_original": currency,
src/jarvis_finance/imports/transactions_importer.py:174:                    fee_original, tax_original, net_amount_original, currency_original,
src/jarvis_finance/imports/transactions_importer.py:175:                    fx_rate_to_chf, fx_source, fx_status, gross_amount_chf, fee_chf,
src/jarvis_finance/imports/transactions_importer.py:176:                    tax_chf, net_amount_chf, source_type, source_id,
src/jarvis_finance/imports/transactions_importer.py:189:                    item["currency_original"], str(fx_rate) if fx_rate is not None else None,
src/jarvis_finance/imports/transactions_importer.py:219:                    evidence={"currency": item["currency_original"], "trade_date": item["trade_date"]},
src/jarvis_finance/imports/cash_balances_importer.py:39:            conn.execute("""INSERT INTO transactions(transaction_id,transaction_type,account_id,trade_date,gross_amount_original,net_amount_original,currency_original,fx_rategrep: src/jarvis_finance/storage/__pycache__/schema.cpython-311.pyc: binary file matches
_to_chf,fx_status,gross_amount_chf,net_amount_chf,source_type,is_confirmed,quality_status,notes,created_at) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,1,?,?,?)""",(cid,'initial_cash_snapshot',aid,date,str(amount),str(amount),cur,str(fx) if fx is not None else None,'ok' if fx is not None else 'missing',str(chf) if chf is not None else None,str(chf) if chf is not None else None,'csv','ok' if fx is not None else 'incomplete',note,now))
src/jarvis_finance/imports/postfinance_etrading.py:68:    amount_chf: Decimal
src/jarvis_finance/imports/postfinance_etrading.py:198:                    amount_chf = fx * amount
src/jarvis_finance/imports/postfinance_etrading.py:200:                    cash.append(PostFinanceCash(currency, fx, amount, amount_chf, reported_account_value, row_hash))
src/jarvis_finance/imports/postfinance_etrading.py:235:        reported_cash_value_chf = sum((item.amount_chf for item in cash), Decimal("0"))
src/jarvis_finance/storage/schema.py:1:INITIAL_SCHEMA_SQL = "\nCREATE TABLE IF NOT EXISTS schema_migrations (\n    version INTEGER PRIMARY KEY,\n    name TEXT NOT NULL,\n    applied_at TEXT NOT NULL,\n    checksum TEXT NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS platforms (\n    platform_id TEXT PRIMARY KEY,\n    name TEXT NOT NULL UNIQUE,\n    platform_type TEXT NOT NULL,\n    country TEXT,\n    default_currency TEXT NOT NULL DEFAULT 'CHF',\n    is_active INTEGER NOT NULL DEFAULT 1,\n    notes TEXT,\n    created_at TEXT NOT NULL,\n    updated_at TEXT\n);\n\nCREATE TABLE IF NOT EXISTS accounts (\n    account_id TEXT PRIMARY KEY,\n    platform_id TEXT NOT NULL REFERENCES platforms(platform_id),\n    account_name TEXT NOT NULL,\n    account_type TEXT NOT NULL,\n    currency TEXT NOT NULL DEFAULT 'CHF',\n    performance_included INTEGER NOT NULL DEFAULT 1,\n    is_health_reserve INTEGER NOT NULL DEFAULT 0,\n    target_cash_min_chf NUMERIC,\n    target_cash_max_chf NUMERIC,\n    is_active INTEGER NOT NULL DEFAULT 1,\n    notes TEXT,\n    created_at TEXT NOT NULL,\n    updated_at TEXT,\n    UNIQUE(platform_id, account_name)\n);\n\nCREATE TABLE IF NOT EXISTS instruments (\n    instrument_id TEXT PRIMARY KEY,\n    asset_class TEXT NOT NULL,\n    name TEXT NOT NULL,\n    ticker TEXT,\n    isin TEXT,\n    exchange TEXT,\n    currency TEXT NOT NULL,\n    country TEXT,\n    sector TEXT,\n    industry TEXT,\n    provider_symbol TEXT,\n    data_provider_primary TEXT,\n    position_category TEXT,\n    ter TEXT,\n    distribution_policy TEXT,\n    index_name TEXT,\n    fund_domicile TEXT,\n    benchmark TEXT,\n    data_provider_fallback TEXT,\n    is_active INTEGER NOT NULL DEFAULT 1,\n    notes TEXT,\n    created_at TEXT NOT NULL,\n    updated_at TEXT\n);\n\nCREATE TABLE IF NOT EXISTS transactions (\n    transaction_id TEXT PRIMARY KEY,\n    transaction_type TEXT NOT NULL,\n    account_id TEXT NOT NULL REFERENCES accounts(account_id),\n    instrument_id TEXT REFERENCES instruments(instrument_id),\n    trade_date TEXT NOT NULL,\n    settlement_date TEXT,\n    quantity TEXT,\n    price_original TEXT,\n    gross_amount_original TEXT,\n    fee_original TEXT DEFAULT '0',\n    tax_original TEXT DEFAULT '0',\n    net_amount_original TEXT,\n    currency_original TEXT NOT NULL,\n    fx_rate_to_chf TEXT,\n    fx_source TEXT,\n    fx_status TEXT NOT NULL DEFAULT 'ok',\n    gross_amount_chf TEXT,\n    fee_chf TEXT,\n    tax_chf TEXT,\n    net_amount_chf TEXT,\n    source_type TEXT NOT NULL,\n    source_id TEXT,\n    external_transaction_id TEXT,\n    row_hash TEXT,\n    is_confirmed INTEGER NOT NULL DEFAULT 1,\n    quality_status TEXT NOT NULL DEFAULT 'ok',\n    notes TEXT,\n    created_at TEXT NOT NULL,\n    updated_at TEXT\n);\n\nCREATE TABLE IF NOT EXISTS positions_snapshot (\n    position_snapshot_id TEXT PRIMARY KEY,\n    snapshot_date TEXT NOT NULL,\n    account_id TEXT NOT NULL REFERENCES accounts(account_id),\n    platform_id TEXT NOT NULL REFERENCES platforms(platform_id),\n    instrument_id TEXT NOT NULL REFERENCES instruments(instrument_id),\n    quantity NUMERIC NOT NULL,\n    average_cost_original NUMERIC,\n    cost_basis_original NUMERIC,\n    cost_basis_chf NUMERIC,\n    market_price_original NUMERIC,\n    market_value_original NUMERIC,\n    market_fx_rate_to_chf NUMERIC,\n    market_value_chf NUMERIC,\n    unrealized_price_pnl_chf NUMERIC,\n    unrealized_fx_pnl_chf NUMERIC,\n    realized_pnl_chf NUMERIC,\n    income_chf NUMERIC,\n    fees_chf NUMERIC,\n    taxes_chf NUMERIC,\n    total_return_chf NUMERIC,\n    portfolio_weight_pct NUMERIC,\n    category TEXT,\n    data_quality_status TEXT NOT NULL DEFAULT 'ok',\n    created_at TEXT NOT NULL,\n    UNIQUE(snapshot_date, account_id, instrument_id)\n);\n\nCREATE TABLE IF NOT EXISTS cash_balances (\n    cash_balance_id TEXT PRIMARY KEY,\n    account_id TEXT NOT NULL REFERENCES accounts(account_id),\n    balance_date TEXT NOT NULL,\n    currency TEXT NOT NULL,\n    amount_original NUMERIC NOT NULL,\n    fx_rate_to_chf NUMERIC,\n    amount_chf NUMERIC,\n    source_type TEXT NOT NULL,\n    quality_status TEXT NOT NULL DEFAULT 'ok',\n    notes TEXT,\n    created_at TEXT NOT NULL,\n    UNIQUE(account_id, balance_date, currency, source_type)\n);\n\nCREATE TABLE IF NOT EXISTS fx_rates (\n    fx_rate_id TEXT PRIMARY KEY,\n    base_currency TEXT NOT NULL,\n    quote_currency TEXT NOT NULL DEFAULT 'CHF',\n    rate_date TEXT NOT NULL,\n    rate_timestamp TEXT,\n    rate NUMERIC NOT NULL,\n    provider TEXT NOT NULL,\n    rate_type TEXT NOT NULL,\n    quality_status TEXT NOT NULL DEFAULT 'ok',\n    created_at TEXT NOT NULL,\n    UNIQUE(base_currency, quote_currency, rate_date, provider, rate_type)\n);\n\nCREATE TABLE IF NOT EXISTS market_prices (\n    market_price_id TEXT PRIMARY KEY,\n    instrument_id TEXT NOT NULL REFERENCES instruments(instrument_id),\n    price_date TEXT NOT NULL,\n    price_timestamp TEXT,\n    open NUMERIC,\n    high NUMERIC,\n    low NUMERIC,\n    close NUMERIC NOT NULL,\n    adjusted_close NUMERIC,\n    currency TEXT NOT NULL,\n    provider TEXT NOT NULL,\n    provider_symbol TEXT,\n    quality_status TEXT NOT NULL DEFAULT 'ok',\n    created_at TEXT NOT NULL,\n    UNIQUE(instrument_id, price_date, provider)\n);\n\nCREATE TABLE IF NOT EXISTS crypto_wallets (\n    wallet_id TEXT PRIMARY KEY,\n    wallet_name TEXT NOT NULL UNIQUE,\n    wallet_type TEXT NOT NULL,\n    platform_provider TEXT,\n    network_chain TEXT,\n    wallet_address TEXT,\n    owner TEXT,\n    is_active INTEGER NOT NULL DEFAULT 1,\n    last_verified_at TEXT,\n    notes TEXT,\n    created_at TEXT NOT NULL,\n    updated_at TEXT\n);\n\nCREATE TABLE IF NOT EXISTS crypto_assets (\n    asset_id TEXT PRIMARY KEY,\n    coin_name TEXT NOT NULL,\n    symbol TEXT NOT NULL,\n    coingecko_id TEXT UNIQUE,\n    network_chain_default TEXT,\n    is_stablecoin INTEGER NOT NULL DEFAULT 0,\n    price_provider_primary TEXT NOT NULL DEFAULT 'CoinGecko',\n    price_provider_fallback TEXT,\n    is_active INTEGER NOT NULL DEFAULT 1,\n    notes TEXT,\n    created_at TEXT NOT NULL,\n    updated_at TEXT\n);\n\nCREATE TABLE IF NOT EXISTS crypto_holdings (\n    crypto_holding_id TEXT PRIMARY KEY,\n    asset_id TEXT NOT NULL REFERENCES crypto_assets(asset_id),\n    wallet_id TEXT NOT NULL REFERENCES crypto_wallets(wallet_id),\n    quantity TEXT NOT NULL,\n    acquisition_source TEXT,\n    last_verified_at TEXT,\n    verification_status TEXT NOT NULL DEFAULT 'unverified',\n    legacy_snapshot_value_original TEXT,\n    legacy_snapshot_value_chf TEXT,\n    legacy_snapshot_currency TEXT,\n    legacy_snapshot_date TEXT,\n    notes TEXT,\n    created_at TEXT NOT NULL,\n    updated_at TEXT,\n    UNIQUE(asset_id, wallet_id)\n);\n\nCREATE TABLE IF NOT EXISTS crypto_transactions (\n    crypto_transaction_id TEXT PRIMARY KEY,\n    transaction_id TEXT REFERENCES transactions(transaction_id),\n    transaction_type TEXT NOT NULL,\n    asset_id TEXT NOT NULL REFERENCES crypto_assets(asset_id),\n    quantity TEXT NOT NULL,\n    price_original TEXT,\n    currency_original TEXT,\n    gross_amount_original TEXT,\n    fee_quantity TEXT,\n    fee_original TEXT,\n    fee_currency TEXT,\n    fx_rate_to_chf TEXT,\n    fx_source TEXT,\n    amount_chf TEXT,\n    from_wallet_id TEXT REFERENCES crypto_wallets(wallet_id),\n    to_wallet_id TEXT REFERENCES crypto_wallets(wallet_id),\n    transaction_datetime TEXT NOT NULL,\n    tx_hash TEXT,\n    source TEXT NOT NULL,\n    confirmation_status TEXT NOT NULL DEFAULT 'confirmed',\n    parse_confidence NUMERIC,\n    original_input_text TEXT,\n    notes TEXT,\n    created_at TEXT NOT NULL,\n    updated_at TEXT\n);\n\nCREATE TABLE IF NOT EXISTS crypto_prices (\n    crypto_price_id TEXT PRIMARY KEY,\n    asset_id TEXT NOT NULL REFERENCES crypto_assets(asset_id),\n    coingecko_id TEXT,\n    price_currency TEXT NOT NULL,\n    price TEXT NOT NULL,\n    provider TEXT NOT NULL DEFAULT 'CoinGecko',\n    provider_timestamp TEXT,\n    fetched_at TEXT NOT NULL,\n    quality_status TEXT NOT NULL DEFAULT 'fresh',\n    error_message TEXT\n);\n\nCREATE TABLE IF NOT EXISTS watchlist (\n    watchlist_id TEXT PRIMARY KEY,\n    instrument_id TEXT REFERENCES instruments(instrument_id),\n    crypto_asset_id TEXT REFERENCES crypto_assets(asset_id),\n    name TEXT NOT NULL,\n    asset_class TEXT NOT NULL,\n    reason TEXT NOT NULL,\n    target_entry_price NUMERIC,\n    target_entry_currency TEXT,\n    desired_position_size_chf NUMERIC,\n    desired_weight_pct NUMERIC,\n    trigger_rules TEXT,\n    risk_notes TEXT,\n    investment_case TEXT,\n    bear_case TEXT,\n    sources TEXT,\n    status TEXT NOT NULL DEFAULT 'active',\n    next_review_date TEXT,\n    created_at TEXT NOT NULL,\n    updated_at TEXT\n);\n\nCREATE TABLE IF NOT EXISTS reports (\n    report_id TEXT PRIMARY KEY,\n    report_type TEXT NOT NULL,\n    title TEXT NOT NULL,\n    period_start TEXT,\n    period_end TEXT,\n    generated_at TEXT NOT NULL,\n    file_path TEXT,\n    format TEXT NOT NULL,\n    data_quality_status TEXT NOT NULL DEFAULT 'ok',\n    summary_json TEXT,\n    created_at TEXT NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS alerts (\n    alert_id TEXT PRIMARY KEY,\n    priority TEXT NOT NULL,\n    category TEXT NOT NULL,\n    entity_type TEXT,\n    entity_id TEXT,\n    rule_id TEXT,\n    message TEXT NOT NULL,\n    evidence_json TEXT,\n    status TEXT NOT NULL DEFAULT 'active',\n    created_at TEXT NOT NULL,\n    resolved_at TEXT,\n    muted_until TEXT,\n    last_seen_at TEXT,\n    occurrence_count INTEGER NOT NULL DEFAULT 1,\n    fingerprint TEXT,\n    dedup_key TEXT\n);\n\nCREATE INDEX IF NOT EXISTS idx_alerts_dedup ON alerts(dedup_key, status);\n\nCREATE TABLE IF NOT EXISTS audit_log (\n    audit_id TEXT PRIMARY KEY,\n    timestamp TEXT NOT NULL,\n    source TEXT NOT NULL,\n    action TEXT NOT NULL,\n    entity_type TEXT NOT NULL,\n    entity_id TEXT NOT NULL,\n    old_values_json TEXT,\n    new_values_json TEXT,\n    user_text_note TEXT,\n    original_input_text TEXT,\n    confirmed INTEGER NOT NULL DEFAULT 1,\n    confirmation_timestamp TEXT,\n    auto_parsed INTEGER NOT NULL DEFAULT 0,\n    parse_confidence NUMERIC,\n    created_by TEXT NOT NULL DEFAULT 'system',\n    quality_status TEXT NOT NULL DEFAULT 'ok',\n    created_at TEXT NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS import_sessions (\n    import_session_id TEXT PRIMARY KEY,\n    import_type TEXT NOT NULL,\n    source_filename TEXT NOT NULL,\n    source_hash TEXT,\n    started_at TEXT NOT NULL,\n    finished_at TEXT,\n    status TEXT NOT NULL,\n    rows_total INTEGER DEFAULT 0,\n    rows_imported INTEGER DEFAULT 0,\n    rows_failed INTEGER DEFAULT 0,\n    errors_json TEXT,\n    notes TEXT\n);\n\nCREATE TABLE IF NOT EXISTS decision_journal (\n    decision_id TEXT PRIMARY KEY,\n    decision_date TEXT NOT NULL,\n    decision_type TEXT NOT NULL,\n    entity_type TEXT,\n    entity_id TEXT,\n    system_recommendation TEXT,\n    human_decision TEXT NOT NULL,\n    rationale TEXT NOT NULL,\n    investment_case TEXT,\n    risks TEXT,\n    exit_rule TEXT,\n    alternatives_considered TEXT,\n    sources TEXT,\n    review_date TEXT,\n    outcome_status TEXT,\n    outcome_return_chf NUMERIC,\n    created_at TEXT NOT NULL,\n    updated_at TEXT\n);\n\nCREATE INDEX IF NOT EXISTS idx_accounts_platform_id ON accounts(platform_id);\nCREATE INDEX IF NOT EXISTS idx_transactions_account_date ON transactions(account_id, trade_date);\nCREATE INDEX IF NOT EXISTS idx_transactions_instrument_date ON transactions(instrument_id, trade_date);\nCREATE INDEX IF NOT EXISTS idx_transactions_type ON transactions(transaction_type);\nCREATE UNIQUE INDEX IF NOT EXISTS idx_transactions_external_id ON transactions(external_transaction_id) WHERE external_transaction_id IS NOT NULL AND external_transaction_id != '';\nCREATE UNIQUE INDEX IF NOT EXISTS idx_transactions_row_hash ON transactions(row_hash) WHERE row_hash IS NOT NULL AND row_hash != '';\nCREATE INDEX IF NOT EXISTS idx_crypto_transactions_asset_datetime ON crypto_transactions(asset_id, transaction_datetime);\nCREATE INDEX IF NOT EXISTS idx_alerts_priority_status ON alerts(priority, status);\nCREATE INDEX IF NOT EXISTS idx_audit_entity ON audit_log(entity_type, entity_id);\n"
src/jarvis_finance/storage/migrations.py:42:    "transactions": {"quantity", "price_original", "gross_amount_original", "fee_original", "tax_original", "net_amount_original", "fx_rate_to_chf", "gross_amount_chf", "fee_chf", "tax_chf", "net_amount_chf"},
src/jarvis_finance/storage/migrations.py:44:    "crypto_transactions": {"quantity", "price_original", "gross_amount_original", "fee_quantity", "fee_original", "fx_rate_to_chf", "amount_chf"},
src/jarvis_finance/storage/migrations.py:567:        CREATE TABLE IF NOT EXISTS budget_transactions (
src/jarvis_finance/storage/migrations.py:577:            currency_original TEXT NOT NULL,
src/jarvis_finance/storage/migrations.py:579:            amount_chf TEXT,
src/jarvis_finance/storage/migrations.py:606:            currency_original TEXT NOT NULL,
src/jarvis_finance/storage/migrations.py:648:            monthly_amount_chf TEXT,
src/jarvis_finance/storage/migrations.py:649:            annual_amount_chf TEXT,
src/jarvis_finance/storage/migrations.py:751:            currency_original TEXT NOT NULL DEFAULT 'CHF',
src/jarvis_finance/storage/migrations.py:787:                currency_original TEXT NOT NULL DEFAULT 'CHF',
src/jarvis_finance/storage/migrations.py:809:                transaction_date, description, merchant, amount_original, currency_original,
src/jarvis_finance/storage/migrations.py:814:                transaction_date, description, merchant, amount_original, currency_original,
src/jarvis_finance/storage/migrations.py:851:            currency_original TEXT NOT NULL DEFAULT 'CHF',
src/jarvis_finance/storage/migrations.py:903:            CREATE TABLE budget_transactions (
src/jarvis_finance/storage/migrations.py:913:                currency_original TEXT NOT NULL,
src/jarvis_finance/storage/migrations.py:915:                amount_chf TEXT,
src/jarvis_finance/storage/migrations.py:928:                description, payee, merchant_id, amount_original, currency_original, fx_rate_to_chf,
src/jarvis_finance/storage/migrations.py:929:                amount_chf, fx_status, category_id, status, source_type, notes, created_at, updated_at,
src/jarvis_finance/storage/migrations.py:933:                description, payee, merchant_id, amount_original, currency_original, fx_rate_to_chf,
src/jarvis_finance/storage/migrations.py:934:                amount_chf, fx_status, category_id, status, source_type, notes, created_at, updated_at,
src/jarvis_finance/storage/migrations.py:955:                currency_original TEXT NOT NULL DEFAULT 'CHF',
src/jarvis_finance/storage/migrations.py:981:                transaction_date, description, merchant, amount_original, currency_original,
src/jarvis_finance/storage/migrations.py:989:                transaction_date, description, merchant, amount_original, currency_original,
src/jarvis_finance/storage/migrations.py:1018:            currency_original TEXT NOT NULL,
src/jarvis_finance/storage/migrations.py:1023:        INSERT OR IGNORE INTO budget_transfers__phase18_fixed(transfer_id, from_transaction_id, to_transaction_id, from_account_id, to_account_id, amount_original, currency_original, fx_rate_to_chf, notes, created_at)
src/jarvis_finance/storage/migrations.py:1024:        SELECT transfer_id, grep: src/jarvis_finance/quality/__pycache__/checks.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/dashboard/__pycache__/data.cpython-312.pyc: binary file matches
grep: src/jarvis_finance/dashboard/__pycache__/data.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/dashboard/views/__pycache__/page_03_equities_etfs.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/api/schemas/__pycache__/positions.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/api/schemas/__pycache__/positions.cpython-312.pyc: binary file matches
from_transaction_id, to_transaction_id, from_account_id, to_account_id, amount_original, currency_original, fx_rate_to_chf, notes, created_at FROM budget_transfers;
src/jarvis_finance/storage/migrations.py:1038:            currency_original TEXT NOT NULL DEFAULT 'CHF',
src/jarvis_finance/storage/migrations.py:1042:        INSERT OR IGNORE INTO budget_import_line_items__phase18_fixed(line_item_id, transaction_candidate_id, source_file_label, receipt_key, source_row_or_range, item_name, quantity, is_promotion, amount_original, currency_original, raw_fingerprint, created_at)
src/jarvis_finance/storage/migrations.py:1043:        SELECT line_item_id, transaction_candidate_id, source_file_label, receipt_key, source_row_or_range, item_name, quantity, is_promotion, amount_original, currency_original, raw_fingerprint, created_at FROM budget_import_line_items;
src/jarvis_finance/storage/migrations.py:1555:            amount_chf TEXT NOT NULL,
src/jarvis_finance/quality/checks.py:11:        "SELECT transaction_id FROM transactions WHERE currency_original != 'CHF' AND (fx_rate_to_chf IS NULL OR fx_status = 'missing')"
src/jarvis_finance/dashboard/views/page_03_equities_etfs.py:53:            "market_value_chf": row.get("amount_chf", ""),
src/jarvis_finance/dashboard/views/page_03_equities_etfs.py:54:            "price_status": "ok" if row.get("amount_chf") else "missing_fx",
src/jarvis_finance/dashboard/views/page_03_equities_etfs.py:55:            "fx_status": "ok" if row.get("amount_chf") else "missing_fx",
src/jarvis_finance/dashboard/views/page_03_equities_etfs.py:57:            "quality_warnings": "" if row.get("amount_chf") else "missing_fx",
src/jarvis_finance/dashboard/views/page_03_equities_etfs.py:321:            tx = data.rowdicts(conn.execute("SELECT trade_date, transaction_type, net_amount_original, currency_original, quality_status, notes FROM transactions WHERE account_id=? AND currency_original=? AND COALESCE(is_voided,0)=0 ORDER BY trade_date DESC, created_at DESC LIMIT 50", (row.get("account_id"), row.get("currency"))).fetchall())
src/jarvis_finance/dashboard/views/page_03_equities_etfs.py:324:            tx = data.rowdicts(conn.execute("SELECT trade_date, transaction_type, quantity, currency_original, quality_status, notes FROM transactions WHERE account_id=? AND instrument_id=? AND COALESCE(is_voided,0)=0 ORDER BY trade_date DESC, created_at DESC", (row["account_id"], row["instrument_id"])).fetchall())
src/jarvis_finance/dashboard/data.py:518:               fw.wallet_name AS from_wallet, tw.wallet_name AS to_wallet, ct.currency_original,
src/jarvis_finance/dashboard/data.py:519:               ct.amount_chf, ct.confirmation_status, ct.source
src/jarvis_finance/dashboard/data.py:552:            "amount_chf": position.used_value_chf,
src/jarvis_finance/dashboard/data.py:710:        totals[row["platform"]] = totals.get(row["platform"], Decimal("0")) + d(row.get("amount_chf"))
src/jarvis_finance/dashboard/data.py:724:               t.net_amount_original, t.currency_original, t.fx_status, t.quality_status,
src/jarvis_finance/dashboard/data.py:1059:        SELECT t.currency_original AS base_currency, 'CHF' AS quote_currency, t.trade_date AS rate_date,
src/jarvis_finance/dashboard/data.py:1063:        LEFT JOIN fx_rates fr ON fr.base_currency=t.currency_original AND fr.quote_currency='CHF' AND fr.rate_date=t.trade_date
src/jarvis_finance/dashboard/data.py:1067:          AND t.currency_original IS NOT NULL
src/jarvis_finance/dashboard/data.py:1068:          AND t.currency_original <> 'CHF'
src/jarvis_finance/dashboard/data.py:1069:        GROUP BY t.currency_original, t.trade_date, fx_status
src/jarvis_finance/dashboard/data.py:1070:        ORDER BY t.currency_original, t.trade_date
src/jarvis_finance/dashboard/data.py:1174:    cash_total = sum(d(r["amount_chf"]) for r in cash_rows if r["amount_chf"])
src/jarvis_finance/api/schemas/positions.py:141:    amount_chf: str
src/jarvis_finance/api/schemas/positions.py:157:    amount_chf: str | None = None
src/jarvis_finance/api/schemas/positions.py:310:    amount_chf: str
src/jagrep: src/jarvis_finance/cli/__pycache__/main.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/equity/__pycache__/manage.cpython-311.pyc: binary file matches
rvis_finance/api/schemas/positions.py:375:    amount_chf: str | None = None
src/jarvis_finance/cli/main.py:227:            currencies = args.currencies or sorted({r["currency_original"] for r in conn.execute("SELECT DISTINCT currency_original FROM transactions WHERE currency_original IS NOT NULL").fetchall()})
src/jarvis_finance/equity/manage.py:256:            currency_original, fx_rate_to_chf, fx_source, fx_status, gross_amount_chf,
src/jarvis_finance/equity/manage.py:257:            fee_chf, tax_chf, net_amount_chf, source_type, source_id, is_confirmed,
src/jarvis_finance/services/manual_entry_service.py:489:    amount_chf = decimal_text(request.amount, 2) if fx_status == "not_needed" else None
src/jarvis_finance/services/manual_entry_service.py:490:    return PreviewResponse(preview_id=_uuid("preview"), summary=f"{request.transaction_type} {request.currency.upper()} {request.amount}", amount_chf=amount_chf, fx_status=fx_status, warnings=warnings)
src/jarvis_finance/services/manual_entry_service.py:505:        INSERT INTO transactions(transaction_id, transaction_type, account_id, trade_date, gross_amount_original, net_amount_original, currency_original, fx_rate_to_chf, fx_status, gross_amount_chf, net_amount_chf, source_type, is_confirmed, quality_status, notes, created_at)
src/jarvis_finance/services/manual_entry_service.py:508:        (balance_id, transaction_type, request.account_id, request.booking_date, amount, amount, request.currency.upper(), fx_rate, "ok" if fx_rate else "missing", preview.amount_chf, preview.amount_chf, quality, request.note, ts),
src/jarvis_finance/services/manual_entry_service.py:512:        INSERT OR IGNORE INTO cash_balances(cash_balance_id, account_id, balance_date, currency, amount_original, fx_rate_to_chf, amount_chf, source_type, quality_status, notes, created_at)
src/jarvis_finance/services/manual_entry_service.py:515:        (_uuid("cash"), request.account_id, request.booking_date, request.currency.upper(), amount, fx_rate, preview.amount_chf, quality, request.note, ts),
src/jarvis_finance/services/manual_entry_service.py:535:    amount_chf = _chf_amount(request.cost_basis_original, Decimal(fx_rate) if fx_rate else None)
src/jarvis_finance/services/manual_entry_service.py:536:    return PreviewResponse(preview_id=_uuid("preview"), asset_class=request.asset_class.lower(), summary=f"{inst['name']} · {request.quantity} · {currency}", amount_chf=amount_chf, fx_status=fx_status, warnings=warnings)
src/jarvis_finance/services/manual_entry_service.py:561:        INSERT INTO transactions(transaction_id, transaction_type, account_id, instrument_id, trade_date, quantity, gross_amount_original, net_amount_original, currency_original, fx_rate_to_chf, fx_source, fx_status, gross_amount_chf, net_amount_chf, source_type, is_confirmed, quality_status, notes, created_at)
src/jarvis_finance/services/manual_entry_service.py:577:            SELECT p.name AS platform, a.account_name, cb.currency, cb.amount_original, cb.amount_chf, cb.quality_status, MAX(cb.created_at) AS last_change
src/jarvis_finance/services/manual_entry_service.py:586:        payload = {"id": position_id, "platform": row["platform"], "account_label": row["account_name"], "currency": row["currency"], "amount": optional_decimal_text(row["amount_original"]) or "0", "amount_chf": optional_decimal_text(row["amount_chf"], 2), "status": row["quality_status"] or "ok"}
src/jarvis_finance/services/manual_entry_service.py:627:        SELECT fx_status, fx_rate_to_chf, currency_original
src/jarvis_finance/services/manual_entry_service.py:661:    currency = str((tx_fx["currency_original"] if tx_fx and tx_fx["currency_original"] else None) or inst_currency or payload.get("currency") or "CHF").upper()
grep: src/jarvis_finance/services/__pycache__/budget_analytics_v2.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/budget_transactions.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/postfinance_service.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/portfolio_performance.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/portfolio_service.cpython-312.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/portfolio_service.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/portfolio_data.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/finance_command_center.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/market_service.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/cash_service.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/budget_analytics.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/budget_recurring.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/portfolio_aggregation.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/reconciliation_snapshot.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/manual_entry_service.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/portfolio_analytics.cpython-312.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/reports_v1.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/budget_plans.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/budget_planning.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/portfolio_performance.cpython-312.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/budget_data_explorer.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/budget_imports.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/budget_seed_review.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/portfolio_aggregation.cpython-312.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/portfolio_analytics.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/budget_overview.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/budget_categories.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/postfinance_service.cpython-312.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/transfer_pairing.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/cash_service.cpython-312.pyc: binary file matches
grep: write error: Broken pipe


git diff -- tests/test_postfinance_sprint13.py | sed -n '1,460p'


Output:
Chunk ID: 1501fa
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 5106
Output:
diff --git a/tests/test_postfinance_sprint13.py b/tests/test_postfinance_sprint13.py
index ecf37e7..1c3e97a 100644
--- a/tests/test_postfinance_sprint13.py
+++ b/tests/test_postfinance_sprint13.py
@@ -1,12 +1,18 @@
 from __future__ import annotations

 import base64
+import json
 from dataclasses import replace
 from decimal import Decimal
 from hashlib import sha256

 import pytest

+from jarvis_finance.dashboard.data import (
+    get_cash_overview,
+    get_command_center_summary,
+    get_positions,
+)
 from jarvis_finance.imports.postfinance_documents import (
     PFBundle,
     PFDocument,
@@ -16,6 +22,15 @@ from jarvis_finance.imports.postfinance_documents import (
     PFSnapshotPosition,
 )
 from jarvis_finance.services import postfinance_service as service
+from jarvis_finance.services.cash_service import get_cash_position_detail, get_cash_summary
+from jarvis_finance.services.equity_service import get_equity_summary
+from jarvis_finance.services.portfolio_aggregation import (
+    latest_official_postfinance_cash,
+    latest_official_postfinance_positions,
+)
+from jarvis_finance.services.portfolio_analytics import confirmed_canonical_positions
+from jarvis_finance.services.portfolio_data import build_portfolio_reconciliation
+from jarvis_finance.services.portfolio_service import get_overview
 from jarvis_finance.storage.database import connect_memory
 from jarvis_finance.storage.migrations import apply_migrations

@@ -461,3 +476,363 @@ def test_immutable_postfinance_source_and_snapshot_rows(monkeypatch, tmp_path):
             conn.execute(f"UPDATE {table} SET created_at=created_at WHERE {predicate}")
         with pytest.raises(Exception, match="cannot be deleted"):
             conn.execute(f"DELETE FROM {table} WHERE {predicate}")
+
+
+def test_global_read_model_counts_official_postfinance_components_once(monkeypatch, tmp_path):
+    """Reproduce the production placeholder/exposure/settlement-position collision."""
+    conn = make_conn()
+    monkeypatch.setenv("JARVIS_FINANCE_RUNTIME_DIR", str(tmp_path))
+    original = bundle()
+    stock_total = Decimal("255791.97")
+    etf_total = Decimal("37673.19")
+
+    def split_total(total: Decimal) -> list[Decimal]:
+        values = [(total / Decimal("11")).quantize(Decimal("0.01")) for _ in range(11)]
+        values[-1] += total - sum(values, Decimal("0"))
+        return values
+
+    source_values = split_total(stock_total) + split_total(etf_total)
+    positions = tuple(
+        replace(item, quantity=Decimal("1"), market_price_original=value, market_value_chf=value)
+        for item, value in zip(original.snapshot.positions, source_values, strict=True)
+    )
+    realistic = replace(
+        original,
+        snapshot=replace(
+            original.snapshot,
+            positions=positions,
+            cash=(
+                PFSnapshotCash("EUR", Decimal("21693.27"), Decimal("0.9293"), Decimal("71623.09")),
+                PFSnapshotCash("USD", Decimal("9235.55"), Decimal("0.8146"), Decimal("249526.14")),
+            ),
+            securities_total_chf=Decimal("293465.16"),
+            cash_total_chf=Decimal("27684.07"),
+            total_value_chf=Decimal("321149.23"),
+            stock_total_chf=stock_total,
+            etf_total_chf=etf_total,
+        ),
+    )
+    monkeypatch.setattr(service, "parse_postfinance_bundle", lambda _zip, _overview: realistic)
+    conn.execute(
+        """INSERT INTO cash_account_snapshots(snapshot_id,account_id,snapshot_type,balance_date,
+               amount_original,currency,amount_chf,source,note,created_at,created_by)
+           VALUES('legacy-total',?,'manual_balance','2026-07-26','321149.23','CHF',
+                  '321149.23','manual','historical depot total placeholder',
+                  '2026-07-26T00:00:00Z','synthetic')""",
+        (CASH,),
+    )
+    conn.execute(
+        "INSERT INTO platforms(platform_id,name,platform_type,country,default_currency,is_active,created_at) VALUES('tw','True Wealth','wealth','CH','CHF',1,'2026-01-01')"
+    )
+    conn.execute(
+        """INSERT INTO accounts(account_id,platform_id,account_name,account_type,currency,
+               performance_included,is_active,created_at,portfolio_bucket)
+           VALUES('account_tw','tw','True Wealth','brokerage','CHF',1,1,'2026-01-01','truewealth')"""
+    )
+    conn.execute(
+        """INSERT INTO account_value_snapshots(snapshot_id,account_id,valuation_date,
+               total_value_chf,currency,source_type,quality_status,created_at,is_active)
+           VALUES('tw-value','account_tw','2026-07-27','152845.00','CHF',
+                  'synthetic_truewealth','complete','2026-07-27T00:00:00Z',1)"""
+    )
+    conn.commit()
+
+    payload = request()
+    preview = service.preview_postfinance_import(conn, payload)
+    service.confirm_postfinance_import(
+        conn,
+        {**payload, "preview_id": preview["preview_id"],
+         "confirmation_id": preview["confirmation_id"], "confirm": True},
+    )
+    before_gets = conn.total_changes
+    cash = get_cash_summary(conn)
+    equity = get_equity_summary(conn)
+    overview = get_overview(conn)
+    command = get_command_center_summary(conn)
+    reconciliation = build_portfolio_reconciliation(conn, as_of="2026-07-27")
+    rows = get_positions(conn)
+
+    assert conn.total_changes == before_gets
+    assert cash.cash_chf == "27684.07"
+    assert sum(Decimal(item.used_value_chf) for item in cash.positions if item.account_id == CASH) == Decimal("27684.07")
+    usd_position = next(item for item in cash.positions if item.account_id == CASH and item.currency == "USD")
+    assert get_cash_position_detail(conn, usd_position.id).currency == "USD"
+    assert equity.equity_value_chf == "293465.16"
+    assert equity.as_of == "2026-07-27T09:14:30+02:00"
+    assert sum(Decimal(row["market_value_chf"]) for row in rows if row["account_id"] == DEPOT) == Decimal("293465.16")
+    assert not [row for row in rows if row["account_id"] == CASH and row["asset_class"] in {"stock", "equity", "etf"}]
+    assert Decimal(cash.cash_chf) + Decimal(equity.equity_value_chf) == Decimal("321149.23")
+    assert overview.truewealth_value_chf == "152845.00"
+    assert command["cash_total_chf"] == "27684.07"
+    pf_reconciliation = next(
+        item for item in reconciliation["account_totals"]
+        if item["reported_total"] == "321149.23"
+    )
+    assert pf_reconciliation["derived_total"] == "321149.23"
+    assert pf_reconciliation["status"] == "matched"
+    assert conn.execute("SELECT amount_chf FROM cash_account_snapshots WHERE snapshot_id='legacy-total'").fetchone()[0] == "321149.23"
+    assert conn.execute("SELECT COUNT(*) FROM transactions WHERE internal_transfer_group_id IS NOT NULL").fetchone()[0] == 2
+
+    market_positions = []
+    for row, value in zip(
+        [row for row in rows if row["account_id"] == DEPOT],
+        split_total(Decimal("160000")) + split_total(Decimal("140000")),
+        strict=True,
+    ):
+        market_positions.append({
+            "account_id": DEPOT, "instrument_id": row["instrument_id"],
+            "quality_status": "fresh", "value_chf": str(value), "close": str(value),
+            "currency": "CHF", "provider": "synthetic-market",
+        })
+    conn.execute(
+        """INSERT INTO market_data_runs(run_id,source_key,as_of,input_fingerprint,status,
+               started_at,completed_at,price_total,price_stored,fx_total,fx_stored,
+               benchmark_total,benchmark_stored,valuation_stored,missing_instruments_json,
+               reason_codes_json)
+           VALUES('newer-run','synthetic','2026-07-28','fp','complete','2026-07-28T00:00:00Z',
+                  '2026-07-28T00:01:00Z',22,22,0,0,0,0,22,'[]','[]')"""
+    )
+    conn.execute(
+        """INSERT INTO portfolio_analysis_snapshots(analysis_snapshot_id,run_id,as_of,
+               base_currency,total_value_chf,price_coverage_pct,fx_coverage_pct,
+               benchmark_coverage_pct,quality_status,reason_codes_json,summary_json,created_at)
+           VALUES('newer-analysis','newer-run','2026-07-28','CHF','300000','100','100','0',
+                  'complete','[]',?,'2026-07-28T00:01:00Z')""",
+        (json.dumps({"positions": market_positions}),),
+    )
+    conn.commit()
+    newer = get_equity_summary(conn)
+    assert newer.equity_value_chf == "300000.00"
+    assert newer.as_of == "2026-07-28"
+    assert get_cash_summary(conn).cash_chf == "27684.07"
+    assert service.get_postfinance_summary(conn)["latest_snapshot"]["total_chf"] == "321149.23"
+
+    duplicate = service.preview_postfinance_import(conn, payload)
+    second = service.confirm_postfinance_import(
+        conn,
+        {**payload, "preview_id": duplicate["preview_id"],
+         "confirmation_id": duplicate["confirmation_id"], "confirm": True},
+    )
+    assert duplicate["duplicate"] is True and duplicate["conflict"] is False
+    assert second["idempotent"] is True
+    assert conn.execute("SELECT COUNT(*) FROM postfinance_import_batches").fetchone()[0] == 1
+
+
+def test_official_snapshot_resolvers_honor_historical_as_of_and_cutoff(monkeypatch, tmp_path):
+    conn = make_conn()
+    monkeypatch.setenv("JARVIS_FINANCE_RUNTIME_DIR", str(tmp_path))
+    monkeypatch.setattr(service, "parse_postfinance_bundle", lambda _zip, _overview: bundle())
+    payload = request()
+    preview = service.preview_postfinance_import(conn, payload)
+    service.confirm_postfinance_import(
+        conn,
+        {**payload, "preview_id": preview["preview_id"],
+         "confirmation_id": preview["confirmation_id"], "confirm": True},
+    )
+    original_cash_total = sum(
+        (item.amount_chf for item in latest_official_postfinance_cash(conn)), Decimal("0")
+    )
+    original_position_total = sum(
+        (
+            item.market_value_chf
+            for item in latest_official_postfinance_positions(conn).values()
+        ),
+        Decimal("0"),
+    )
+    conn.execute("UPDATE accounts SET account_type='checking' WHERE account_id=?", (CASH,))
+    assert sum(
+        (
+            Decimal(item.used_value_chf)
+            for item in get_cash_summary(conn).positions
+            if item.account_id == CASH
+        ),
+        Decimal("0"),
+    ) == original_cash_total
+    platform_id = conn.execute(
+        "SELECT platform_id FROM accounts WHERE account_id=?", (CASH,)
+    ).fetchone()["platform_id"]
+    conn.execute(
+        """INSERT INTO accounts(
+               account_id,platform_id,account_name,account_type,currency,balance_mode,
+               portfolio_bucket,is_active,created_at)
+           VALUES('generic-usd-cash',?,'Generic Multi-Currency','cash','CHF','csv_calculated',
+                  'cash',1,'2026-07-27T10:00:00Z')""",
+        (platform_id,),
+    )
+    conn.execute(
+        """INSERT INTO transactions(
+               transaction_id,transaction_type,account_id,trade_date,gross_amount_original,
+               net_amount_original,currency_original,fx_rate_to_chf,fx_status,source_type,
+               source_id,is_confirmed,quality_status,created_at)
+           VALUES('generic-usd-deposit','cash_deposit','generic-usd-cash','2026-07-27',
+                  '100','100','USD','0.9','ok','csv_import','generic-usd-deposit',1,
+                  'ok','2026-07-27T10:00:00Z')"""
+    )
+    conn.execute(
+        """INSERT INTO transactions(
+               transaction_id,transaction_type,account_id,trade_date,gross_amount_original,
+               net_amount_original,currency_original,fx_rate_to_chf,fx_status,source_type,
+               source_id,is_confirmed,quality_status,created_at)
+           VALUES('generic-eur-deposit','cash_deposit','generic-usd-cash','2026-07-27',
+                  '50','50','EUR','1.1','ok','csv_import','generic-eur-deposit',1,
+                  'ok','2026-07-27T10:00:01Z')"""
+    )
+    generic_rows = [
+        row for row in get_cash_overview(conn) if row["account_id"] == "generic-usd-cash"
+    ]
+    assert {row["currency"] for row in generic_rows} == {"EUR", "USD"}
+    generic_usd = next(row for row in generic_rows if row["currency"] == "USD")
+    generic_eur = next(row for row in generic_rows if row["currency"] == "EUR")
+    assert generic_usd["amount_original"] == "100.00"
+    assert generic_usd["amount_chf"] == "90.00"
+    assert generic_eur["amount_original"] == "50.00"
+    assert generic_eur["amount_chf"] == "55.00"
+    conn.execute(
+        "UPDATE accounts SET balance_mode='manual' WHERE account_id='generic-usd-cash'"
+    )
+    conn.execute(
+        """INSERT INTO cash_account_snapshots(
+               snapshot_id,account_id,snapshot_type,balance_date,amount_original,currency,
+               amount_chf,source,created_at,created_by)
+           VALUES('generic-manual-total','generic-usd-cash','manual_balance','2026-07-27',
+                  '1000','CHF','1000','manual','2026-07-27T10:01:00Z','user')"""
+    )
+    conn.execute(
+        """INSERT INTO cash_balances(
+               cash_balance_id,account_id,balance_date,currency,amount_original,
+               fx_rate_to_chf,amount_chf,source_type,quality_status,created_at)
+           VALUES('generic-missing-fx','generic-usd-cash','2026-07-27','GBP','10',
+                  NULL,NULL,'manual_import','missing_fx','2026-07-27T10:01:01Z')"""
+    )
+    controlled_rows = [
+        row for row in get_cash_overview(conn) if row["account_id"] == "generic-usd-cash"
+    ]
+    assert [(row["currency"], row["amount_chf"]) for row in controlled_rows] == [
+        ("CHF", "1000.00")
+    ]
+
+    batch = dict(conn.execute("SELECT * FROM postfinance_import_batches LIMIT 1").fetchone())
+    batch.update(
+        batch_id="future-batch",
+        bundle_sha256=sha256(b"future-bundle").hexdigest(),
+        snapshot_at="2026-08-01T09:14:30+02:00",
+        confirmed_at="2026-08-01T10:00:00Z",
+    )
+    columns = list(batch)
+    conn.execute(
+        f"INSERT INTO postfinance_import_batches({','.join(columns)}) VALUES({','.join('?' for _ in columns)})",
+        [batch[column] for column in columns],
+    )
+    source_snapshot = dict(conn.execute("SELECT * FROM postfinance_snapshots LIMIT 1").fetchone())
+    source_snapshot.update(
+        snapshot_id="future-snapshot",
+        batch_id="future-batch",
+        snapshot_at="2026-08-01T09:14:30+02:00",
+        total_chf="1299.00",
+        securities_chf="300.00",
+        cash_chf="999.00",
+        stocks_chf="100.00",
+        etfs_chf="200.00",
+        component_total_chf="1299.00",
+        difference_chf="0.00",
+        created_at="2026-08-01T10:00:00Z",
+    )
+    columns = list(source_snapshot)
+    conn.execute(
+        f"INSERT INTO postfinance_snapshots({','.join(columns)}) VALUES({','.join('?' for _ in columns)})",
+        [source_snapshot[column] for column in columns],
+    )
+    conn.execute(
+        """INSERT INTO postfinance_snapshot_positions(
+               snapshot_position_id,snapshot_id,source_row_reference,instrument_id,asset_class,
+               quantity,provider_average_cost_original,provider_cost_total_original,
+               price_original,price_currency,value_chf,weight_pct,computed_cost_basis_original,
+               computed_cost_basis_status,provenance_json,created_at)
+           SELECT 'future-'||snapshot_position_id,'future-snapshot',source_row_reference,
+                  instrument_id,asset_class,quantity,provider_average_cost_original,
+                  provider_cost_total_original,price_original,price_currency,value_chf,weight_pct,
+                  computed_cost_basis_original,computed_cost_basis_status,provenance_json,
+                  '2026-08-01T10:00:00Z'
+           FROM postfinance_snapshot_positions WHERE snapshot_id<> 'future-snapshot'"""
+    )
+    conn.execute(
+        """INSERT INTO postfinance_snapshot_cash(
+               snapshot_cash_id,snapshot_id,currency,amount_original,fx_rate_to_chf,value_chf,created_at)
+           SELECT 'future-'||snapshot_cash_id,'future-snapshot',currency,amount_original,
+                  fx_rate_to_chf,value_chf,'2026-08-01T10:00:00Z'
+           FROM postfinance_snapshot_cash WHERE snapshot_id<> 'future-snapshot'"""
+    )
+    conn.commit()
+
+    assert sum((item.amount_chf for item in latest_official_postfinance_cash(conn)), Decimal("0")) == Decimal("999.00")
+    historical_cash = latest_official_postfinance_cash(conn, as_of="2026-07-27")
+    assert sum((item.amount_chf for item in historical_cash), Decimal("0")) == original_cash_total
+    cutoff_cash = latest_official_postfinance_cash(
+        conn,
+        as_of="2026-08-01",
+        data_cutoff="2026-07-31T23:59:59Z",
+    )
+    assert sum((item.amount_chf for item in cutoff_cash), Decimal("0")) == original_cash_total
+    historical_positions = latest_official_postfinance_positions(conn, as_of="2026-07-27")
+    assert sum(
+        (item.market_value_chf for item in historical_positions.values()), Decimal("0")
+    ) == original_position_total
+    assert {item.valuation_at for item in historical_positions.values()} == {"2026-07-27T09:14:30+02:00"}
+    current_positions = latest_official_postfinance_positions(conn)
+    assert sum((item.market_value_chf for item in current_positions.values()), Decimal("0")) == Decimal("300.00")
+    assert {item.valuation_at for item in current_positions.values()} == {"2026-08-01T09:14:30+02:00"}
+
+    selected = next(iter(current_positions.values()))
+    baseline_quantity = selected.quantity
+    conn.execute(
+        """INSERT INTO transactions(
+               transaction_id,transaction_type,account_id,instrument_id,trade_date,
+               settlement_date,quantity,currency_original,source_type,source_id,
+               external_transaction_id,row_hash,is_confirmed,quality_status,created_at,
+               updated_at,is_voided)
+           VALUES('post-snapshot-buy','buy',?,?, '2026-08-02','2026-08-02','2',
+                  'CHF','manual_confirmed_trade','post-snapshot-buy','post-snapshot-buy',?,
+                  1,'ok','2026-08-02T10:00:00Z','2026-08-02T10:00:00Z',0)""",
+        (CASH, selected.instrument_id, sha256(b"post-snapshot-buy").hexdigest()),
+    )
+    conn.execute(
+        """INSERT INTO transactions(
+               transaction_id,transaction_type,account_id,trade_date,gross_amount_original,
+               net_amount_original,currency_original,fx_rate_to_chf,fx_status,source_type,
+               source_id,is_confirmed,quality_status,created_at,is_voided)
+           VALUES('post-snapshot-cash','cash_deposit',?,'2026-08-02','10','10','USD',
+                  '0.8','ok','manual_confirmed_cash','post-snapshot-cash',1,'ok',
+                  '2026-08-02T10:01:00Z',0)""",
+        (CASH,),
+    )
+    conn.execute(
+        """INSERT INTO transactions(
+               transaction_id,transaction_type,account_id,instrument_id,trade_date,
+               settlement_date,quantity,gross_amount_original,net_amount_original,
+               currency_original,fx_rate_to_chf,fx_status,source_type,source_id,
+               is_confirmed,quality_status,created_at,is_voided)
+           VALUES('post-snapshot-sell','sell',?,?, '2026-08-02','2026-08-02','1',
+                  '20','20','USD','0.8','ok','manual_confirmed_trade',
+                  'post-snapshot-sell',1,'ok','2026-08-02T10:02:00Z',0)""",
+        (CASH, selected.instrument_id),
+    )
+    conn.commit()
+    post_snapshot_cash = [
+        item for item in get_cash_summary(conn).positions if item.account_id == CASH
+    ]
+    assert sum(
+        (Decimal(item.used_value_chf) for item in post_snapshot_cash), Decimal("0")
+    ) == Decimal("1023.00")
+    assert next(item for item in post_snapshot_cash if item.currency == "USD").amount == "130.00"
+    dashboard_position = next(
+        row
+        for row in get_positions(conn)
+        if row["account_id"] == DEPOT and row["instrument_id"] == selected.instrument_id
+    )
+    assert Decimal(dashboard_position["quantity"]) == baseline_quantity + Decimal("1")
+    canonical_position = next(
+        item
+        for item in confirmed_canonical_positions(conn, as_of="2026-08-02")
+        if item.account_id == DEPOT and item.instrument_id == selected.instrument_id
+    )
+    assert canonical_position.quantity == baseline_quantity + Decimal("1")


Output:
Chunk ID: 640fff
Wall time: 2.2200 seconds
Process exited with code 0
Original token count: 25
Output:
........                                                                 [100%]
8 passed in 2.04s


git diff -- src/jarvis_finance/services/postfinance_service.py | sed -n '440,620p' && git diff -- src/jarvis_finance/services/postfinance_service.py | sed -n '1,220p'


Output:
Chunk ID: bf4e53
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 900
Output:
diff --git a/src/jarvis_finance/services/postfinance_service.py b/src/jarvis_finance/services/postfinance_service.py
index 9ea4ba8..b34d319 100644
--- a/src/jarvis_finance/services/postfinance_service.py
+++ b/src/jarvis_finance/services/postfinance_service.py
@@ -2,12 +2,12 @@ from __future__ import annotations

 import base64
 import binascii
+import json
+import os
 from collections import defaultdict
 from datetime import UTC, datetime
 from decimal import Decimal
 from hashlib import sha256
-import json
-import os
 from pathlib import Path
 from sqlite3 import Connection, IntegrityError
 from typing import Any
@@ -22,6 +22,10 @@ from jarvis_finance.imports.postfinance_documents import (
     normalize_label,
     parse_postfinance_bundle,
 )
+from jarvis_finance.services.portfolio_aggregation import (
+    latest_official_postfinance_cash,
+    latest_official_postfinance_positions,
+)

 TOLERANCE = Decimal("0.05")

@@ -876,6 +880,10 @@ def get_postfinance_summary(conn: Connection) -> dict[str, Any]:
             "event_counts": {},
             "imports": [],
         }
+    official_position_values = {
+        override.instrument_id: override.market_value_chf
+        for override in latest_official_postfinance_positions(conn).values()
+    }
     positions = [
         {
             "row_key": _hash("position", row["instrument_name"], row["quantity"])[:16],
@@ -887,13 +895,13 @@ def get_postfinance_summary(conn: Connection) -> dict[str, Any]:
             "provider_cost_total_original": row["provider_cost_total_original"],
             "price_original": row["price_original"],
             "price_currency": row["price_currency"],
-            "value_chf": row["value_chf"],
+            "value_chf": _money(official_position_values.get(row["instrument_id"], Decimal(str(row["value_chf"])))),
             "weight_pct": row["weight_pct"],
             "computed_cost_basis_original": row["computed_cost_basis_original"],
             "computed_cost_basis_status": row["computed_cost_basis_status"],
         }
         for row in conn.execute(
-            """SELECT p.asset_class,p.quantity,p.provider_average_cost_original,
+            """SELECT p.instrument_id,p.asset_class,p.quantity,p.provider_average_cost_original,
                       p.provider_cost_total_original,p.price_original,p.price_currency,p.value_chf,
                       p.weight_pct,p.computed_cost_basis_original,p.computed_cost_basis_status,
                       i.name AS instrument_name,i.ticker
@@ -905,17 +913,13 @@ def get_postfinance_summary(conn: Connection) -> dict[str, Any]:
     ]
     cash = [
         {
-            "row_key": _hash("cash", row["currency"])[:16],
-            "currency": row["currency"],
-            "amount_original": row["amount_original"],
-            "fx_rate_to_chf": row["fx_rate_to_chf"],
-            "value_chf": row["value_chf"],
+            "row_key": _hash("cash", component.currency)[:16],
+            "currency": component.currency,
+            "amount_original": _text(component.amount_original),
+            "fx_rate_to_chf": _text(component.source_fx_rate_to_chf),
+            "value_chf": _money(component.amount_chf),
         }
-        for row in conn.execute(
-            """SELECT currency,amount_original,fx_rate_to_chf,value_chf
-               FROM postfinance_snapshot_cash WHERE snapshot_id=? ORDER BY currency""",
-            (latest["snapshot_id"],),
-        ).fetchall()
+        for component in latest_official_postfinance_cash(conn)
     ]
     events = {
         str(row["event_type"]): int(row["c"])


sed -n '1,520p' src/jarvis_finance/services/cash_service.py


Output:
Chunk ID: db86a7
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 5001
Output:
from __future__ import annotations

import json
from datetime import UTC, datetime
from decimal import Decimal, InvalidOperation
from sqlite3 import Connection
from uuid import uuid4

from fastapi import HTTPException

from jarvis_finance.api.schemas.overview import CashSummary
from jarvis_finance.api.schemas.positions import (
    ActionItem,
    CashPosition,
    CashPositionDetail,
    CashSnapshot,
    CashSnapshotConfirmRequest,
    CashSnapshotPreviewRequest,
    ConfirmResponse,
    PreviewResponse,
)
from jarvis_finance.ledger.cash import _signed_cash_delta, calculate_cash_balances
from jarvis_finance.services.api_helpers import decimal_text
from jarvis_finance.services.portfolio_aggregation import latest_official_postfinance_cash

CANONICAL_CASH_ACCOUNTS = [
    {"platform": "Raiffeisen", "account_name": "Raiffeisen", "balance_mode": "csv_calculated"},
    {"platform": "PostFinance Cash", "account_name": "PostFinance Cash-Konto", "balance_mode": "manual"},
    {"platform": "AKB", "account_name": "AKB Zinsbereitstellungskonto", "balance_mode": "manual"},
    {"platform": "AKB", "account_name": "AKB gemeinsames Konto", "balance_mode": "manual"},
    {"platform": "AKB", "account_name": "AKB Aargauer-Sparkonto", "balance_mode": "manual"},
    {"platform": "AKB", "account_name": "AKB Haushaltskonto", "balance_mode": "csv_calculated"},
]

def _now() -> str:
    return datetime.now(UTC).replace(microsecond=0).isoformat().replace("+00:00", "Z")

def _uuid(prefix: str) -> str:
    return f"{prefix}_{uuid4().hex[:16]}"

def _decimal(value: str, field: str) -> Decimal:
    try:
        parsed = Decimal(str(value))
    except (InvalidOperation, ValueError) as exc:
        raise HTTPException(status_code=422, detail=f"Invalid decimal for {field}") from exc
    if parsed < 0:
        raise HTTPException(status_code=422, detail=f"{field} must be zero or positive")
    return parsed

def _audit(conn: Connection, *, action: str, entity_type: str, entity_id: str, payload: dict, note: str, created_by: str = "user") -> str:
    audit_id = _uuid("audit")
    ts = _now()
    conn.execute(
        """
        INSERT INTO audit_log(audit_id, timestamp, source, action, entity_type, entity_id, old_values_json, new_values_json, user_text_note, confirmed, confirmation_timestamp, created_by, quality_status, created_at)
        VALUES (?, ?, 'vue_dashboard', ?, ?, ?, NULL, ?, ?, 1, ?, ?, 'ok', ?)
        """,
        (audit_id, ts, action, entity_type, entity_id, json.dumps(payload, sort_keys=True), note, ts, created_by, ts),
    )
    return audit_id

def _ensure_platform(conn: Connection, name: str) -> str:
    row = conn.execute("SELECT platform_id FROM platforms WHERE lower(name)=lower(?)", (name,)).fetchone()
    if row:
        return row["platform_id"]
    platform_id = _uuid("plat")
    conn.execute(
        "INSERT INTO platforms(platform_id, name, platform_type, default_currency, created_at) VALUES (?, ?, 'bank', 'CHF', ?)",
        (platform_id, name, _now()),
    )
    return platform_id

def ensure_canonical_cash_accounts(conn: Connection, *, created_by: str = "user") -> dict:
    created: list[str] = []
    existing_names = [item["account_name"] for item in CANONICAL_CASH_ACCOUNTS]
    duplicates = [
        row["account_name"]
        for row in conn.execute(
            f"""
            SELECT account_name, COUNT(*) AS n
            FROM accounts
            WHERE account_type='cash' AND account_name IN ({','.join('?' for _ in existing_names)})
            GROUP BY account_name HAVING COUNT(*) > 1
            """,
            existing_names,
        ).fetchall()
    ]
    for item in CANONICAL_CASH_ACCOUNTS:
        rows = conn.execute("SELECT account_id FROM accounts WHERE account_type='cash' AND account_name=?", (item["account_name"],)).fetchall()
        if len(rows) > 1:
            continue
        platform_id = _ensure_platform(conn, item["platform"])
        if rows:
            account_id = rows[0]["account_id"]
            conn.execute(
                "UPDATE accounts SET platform_id=?, currency='CHF', balance_mode=?, portfolio_bucket='cash', updated_at=? WHERE account_id=?",
                (platform_id, item["balance_mode"], _now(), account_id),
            )
        else:
            account_id = _uuid("acct")
            conn.execute(
                """
                INSERT INTO accounts(account_id, platform_id, account_name, account_type, currency, balance_mode, portfolio_bucket, is_active, created_at)
                VALUES (?, ?, ?, 'cash', 'CHF', ?, 'cash', 1, ?)
                """,
                (account_id, platform_id, item["account_name"], item["balance_mode"], _now()),
            )
            created.append(item["account_name"])
            _audit(conn, action="cash_account_seed_confirm", entity_type="cash_account", entity_id=account_id, payload=item, note="Canonical cash account ensured", created_by=created_by)
    conn.commit()
    return {"created": len(created), "created_accounts": created, "duplicates": duplicates}

def _latest_snapshot(conn: Connection, account_id: str, snapshot_type: str):
    return conn.execute(
        """
        SELECT * FROM cash_account_snapshots
        WHERE account_id=? AND snapshot_type=?
        ORDER BY balance_date DESC, created_at DESC
        LIMIT 1
        """,
        (account_id, snapshot_type),
    ).fetchone()

def _cash_movements_after_anchor(conn: Connection, account_id: str, anchor_date: str | None) -> Decimal:
    if not anchor_date:
        return Decimal("0")
    row = conn.execute(
        """
        SELECT COALESCE(SUM(CAST(net_amount_chf AS TEXT)), '0') AS movement
        FROM transactions
        WHERE account_id=? AND COALESCE(is_voided,0)=0 AND COALESCE(is_confirmed,1)=1
          AND source_type LIKE '%csv%'
          AND trade_date > ?
        """,
        (account_id, anchor_date),
    ).fetchone()
    return Decimal(str(row["movement"] or "0"))

def _calculated_balance(conn: Connection, account_id: str) -> Decimal:
    anchor = _latest_snapshot(conn, account_id, "csv_anchor_balance")
    if anchor:
        return Decimal(str(anchor["amount_chf"])) + _cash_movements_after_anchor(conn, account_id, anchor["balance_date"])
    rows = conn.execute(
        "SELECT amount_chf FROM cash_balances WHERE account_id=?",
        (account_id,),
    ).fetchall()
    if rows:
        return sum(
            (
                Decimal(str(row["amount_chf"]))
                for row in rows
                if row["amount_chf"] is not None
            ),
            Decimal("0"),
        )
    # Legacy/demo datasets can have a transaction ledger without materialized
    # cash_balances. Keep the shared read model compatible without overriding an
    # explicit snapshot projection.
    ledger = calculate_cash_balances(conn, persist_alerts=False)
    return sum(
        (
            balance.amount_chf
            for (ledger_account_id, _currency), balance in ledger.balances.items()
            if ledger_account_id == account_id and balance.amount_chf is not None
        ),
        Decimal("0"),
    )

def _last_imported_booking(conn: Connection, account_id: str) -> str | None:
    row = conn.execute("SELECT MAX(trade_date) AS last_date FROM transactions WHERE account_id=? AND source_type LIKE '%csv%'", (account_id,)).fetchone()
    return row["last_date"] if row else None

def _post_snapshot_cash_deltas(
    conn: Connection,
    account_id: str,
    snapshot_date: str,
) -> dict[str, tuple[Decimal, Decimal | None]]:
    rows = conn.execute(
        """SELECT * FROM transactions
           WHERE account_id=? AND trade_date>?
             AND COALESCE(is_confirmed,0)=1 AND COALESCE(is_voided,0)=0
           ORDER BY trade_date,created_at,transaction_id""",
        (account_id, snapshot_date),
    ).fetchall()
    deltas: dict[str, tuple[Decimal, Decimal | None]] = {}
    for row in rows:
        original, amount_chf = _signed_cash_delta(row)
        if original == 0 and amount_chf in {None, Decimal("0")}:
            continue
        currency = str(row["currency_original"])
        previous_original, previous_chf = deltas.get(
            currency,
            (Decimal("0"), Decimal("0")),
        )
        deltas[currency] = (
            previous_original + original,
            None
            if previous_chf is None or amount_chf is None
            else previous_chf + amount_chf,
        )
    return deltas

def list_cash_positions(conn: Connection) -> list[CashPosition]:
    ledger = calculate_cash_balances(conn, persist_alerts=False)
    rows = conn.execute(
        """
        SELECT a.account_id, a.account_name, a.account_type, a.currency, COALESCE(a.balance_mode,'manual') AS balance_mode, p.name AS platform
        FROM accounts a JOIN platforms p ON p.platform_id=a.platform_id
        WHERE a.is_active=1
          AND (
              a.account_type='cash'
              OR a.account_id IN (
                  SELECT account_id FROM postfinance_account_roles
                  WHERE role='etrading_cash'
              )
          )
        ORDER BY p.name, a.account_name
        """
    ).fetchall()
    positions: list[CashPosition] = []
    official_components = latest_official_postfinance_cash(conn)
    official_by_account: dict[str, list] = {}
    for component in official_components:
        official_by_account.setdefault(component.account_id, []).append(component)
    for row in rows:
        account_id = row["account_id"]
        if account_id in official_by_account:
            components = {
                component.currency: component
                for component in official_by_account[account_id]
            }
            snapshot_date = next(iter(components.values())).snapshot_date
            deltas = _post_snapshot_cash_deltas(conn, account_id, snapshot_date)
            for currency in sorted(set(components) | set(deltas)):
                component = components.get(currency)
                delta_original, delta_chf = deltas.get(
                    currency,
                    (Decimal("0"), Decimal("0")),
                )
                amount_original = (
                    component.amount_original if component else Decimal("0")
                ) + delta_original
                baseline_chf = component.amount_chf if component else Decimal("0")
                amount_chf = (
                    baseline_chf + delta_chf if delta_chf is not None else baseline_chf
                )
                status = (
                    "Abgleich offen"
                    if delta_chf is None
                    else "Offiziell abgeglichen + Bewegungen"
                    if delta_original or delta_chf
                    else "Offiziell abgeglichen"
                )
                positions.append(
                    CashPosition(
                        id=f"{account_id}:{currency}",
                        account_id=account_id,
                        platform=row["platform"],
                        account_label=row["account_name"],
                        account_type=row["account_type"],
                        currency=currency,
                        balance_mode="official_components",
                        amount=decimal_text(amount_original, 2),
                        amount_chf=decimal_text(amount_chf, 2),
                        calculated_balance_chf=decimal_text(amount_chf, 2),
                        manual_balance_chf=None,
                        csv_anchor_balance_chf=None,
                        used_value_chf=decimal_text(amount_chf, 2),
                        difference_chf="0.00",
                        last_manual_reconciliation=snapshot_date,
                        last_imported_booking=_last_imported_booking(conn, account_id),
                        status=status,
                    )
                )
            continue
        manual = _latest_snapshot(conn, account_id, "manual_balance")
        anchor = _latest_snapshot(conn, account_id, "csv_anchor_balance")
        mode = row["balance_mode"] or "manual"
        default_currency = str(row["currency"])
        ledger_currencies = {
            currency
            for ledger_account_id, currency in ledger.balances
            if ledger_account_id == account_id
        }
        # Manual balances and CSV anchors are account-level CHF controls. They must
        # not be added to per-currency ledger rows from the same account.
        currencies = (
            {default_currency}
            if manual or anchor
            else set(ledger_currencies) or {default_currency}
        )
        for currency in sorted(currencies):
            ledger_balance = ledger.balances.get((account_id, currency))
            if ledger_balance is not None:
                calculated = ledger_balance.amount_chf or Decimal("0")
                amount_original = ledger_balance.amount_original
            else:
                calculated = _calculated_balance(conn, account_id)
                amount_original = (
                    calculated if currency.upper() == "CHF" else Decimal("0")
                )
            manual_amount = (
                Decimal(str(manual["amount_chf"]))
                if manual and currency == default_currency
                else None
            )
            used = (
                manual_amount
                if mode == "manual" and manual_amount is not None
                else calculated
            )
            difference = (
                manual_amount - calculated
                if manual_amount is not None
                else Decimal("0")
            )
            status = "Abgleich offen" if manual_amount is not None and difference != 0 else "Aktuell"
            positions.append(
                CashPosition(
                    id=f"{account_id}:{currency}",
                    account_id=account_id,
                    platform=row["platform"],
                    account_label=row["account_name"],
                    account_type=row["account_type"],
                    currency=currency,
                    balance_mode=mode,
                    amount=decimal_text(amount_original, 2),
                    amount_chf=decimal_text(used, 2),
                    calculated_balance_chf=decimal_text(calculated, 2),
                    manual_balance_chf=(
                        decimal_text(manual_amount, 2)
                        if manual_amount is not None
                        else None
                    ),
                    csv_anchor_balance_chf=(
                        decimal_text(anchor["amount_chf"], 2)
                        if anchor and currency == default_currency
                        else None
                    ),
                    used_value_chf=decimal_text(used, 2),
                    difference_chf=decimal_text(difference, 2),
                    last_manual_reconciliation=(
                        manual["balance_date"]
                        if manual and currency == default_currency
                        else None
                    ),
                    last_imported_booking=_last_imported_booking(conn, account_id),
                    status=status,
                )
            )
    return positions

def get_cash_summary(conn: Connection) -> CashSummary:
    # Read paths must never seed or refresh accounts; setup is an explicit Confirm action.
    positions = list_cash_positions(conn)
    total = sum(Decimal(p.used_value_chf) for p in positions)
    last_dates = [p.last_manual_reconciliation for p in positions if p.last_manual_reconciliation]
    return CashSummary(
        base_currency="CHF",
        cash_chf=decimal_text(total, 2),
        manual_accounts_count=sum(1 for p in positions if p.balance_mode == "manual"),
        csv_calculated_accounts_count=sum(1 for p in positions if p.balance_mode == "csv_calculated"),
        open_reconciliation_count=sum(1 for p in positions if p.status == "Abgleich offen"),
        last_reconciliation_at=max(last_dates) if last_dates else None,
        positions=positions,
    )

def preview_cash_snapshot(conn: Connection, request: CashSnapshotPreviewRequest) -> PreviewResponse:
    row = conn.execute("SELECT account_id, account_type FROM accounts WHERE account_id=?", (request.account_id,)).fetchone()
    if not row or row["account_type"] != "cash":
        raise HTTPException(status_code=404, detail="Cash account not found")
    if request.snapshot_type not in {"manual_balance", "csv_anchor_balance", "calculated_balance", "reconciliation"}:
        raise HTTPException(status_code=422, detail="Invalid snapshot_type")
    amount = _decimal(request.amount_chf, "amount_chf")
    return PreviewResponse(preview_id=_uuid("preview"), asset_class="cash", summary=f"{request.snapshot_type} CHF per {request.balance_date}", amount_chf=decimal_text(amount, 2), fx_status="not_needed", warnings=[])

def confirm_cash_snapshot(conn: Connection, request: CashSnapshotConfirmRequest) -> ConfirmResponse:
    if not request.confirm:
        raise HTTPException(status_code=400, detail="Explicit confirm required")
    preview_cash_snapshot(conn, request)
    amount = _decimal(request.amount_chf, "amount_chf")
    snapshot_id = _uuid("cashsnap")
    now = _now()
    source = "manual" if request.snapshot_type in {"manual_balance", "reconciliation"} else "csv_import" if request.snapshot_type == "csv_anchor_balance" else "system_calculated"
    audit_id = _audit(conn, action=f"cash_{request.snapshot_type}_confirm", entity_type="cash_account", entity_id=request.account_id, payload=request.model_dump(), note=request.note)
    conn.execute(
        """
        INSERT INTO cash_account_snapshots(snapshot_id, account_id, snapshot_type, balance_date, amount_original, currency, amount_chf, source, note, created_at, created_by, audit_id)
        VALUES (?, ?, ?, ?, ?, 'CHF', ?, ?, ?, ?, 'user', ?)
        """,
        (snapshot_id, request.account_id, request.snapshot_type, request.balance_date, decimal_text(amount, 2), decimal_text(amount, 2), source, request.note, now, audit_id),
    )
    conn.commit()
    return ConfirmResponse(status="confirmed", entity_id=snapshot_id, audit_id=audit_id, message="Kontostand gespeichert · Audit geschrieben")

def get_cash_position_detail(conn: Connection, position_id: str) -> CashPositionDetail:
    position = next((p for p in get_cash_summary(conn).positions if p.id == position_id), None)
    if not position:
        raise HTTPException(status_code=404, detail="Cash position not found")
    account_id = position.account_id
    rows = conn.execute(
        """
        SELECT snapshot_id, snapshot_type, balance_date, amount_chf, source, COALESCE(note,'') AS note, audit_id
        FROM cash_account_snapshots
        WHERE account_id=?
        ORDER BY balance_date DESC, created_at DESC
        LIMIT 30
        """,
        (account_id,),
    ).fetchall()
    history: list[CashSnapshot] = []
    previous: Decimal | None = None
    for row in reversed(rows):
        current = Decimal(str(row["amount_chf"]))
        diff = None if previous is None else decimal_text(current - previous, 2)
        previous = current
        history.append(CashSnapshot(snapshot_id=row["snapshot_id"], snapshot_type=row["snapshot_type"], balance_date=row["balance_date"], amount_chf=decimal_text(current, 2), source=row["source"], note=row["note"], difference_to_previous_chf=diff, audit_hint="Audit vorhanden" if row["audit_id"] else None))
    history = list(reversed(history))
    return CashPositionDetail(**position.model_dump(), last_change=position.last_manual_reconciliation, history=history, available_actions=[ActionItem(label="Einzahlung", enabled=True), ActionItem(label="Auszahlung", enabled=True), ActionItem(label="Kontostand aktualisieren", enabled=True), ActionItem(label="CSV-Anfangsstand setzen", enabled=True), ActionItem(label="Abgleich bestätigen", enabled=True), ActionItem(label="Verlauf anzeigen", enabled=True)])


sed -n '1,130p' src/jarvis_finance/ledger/cash.py && sed -n '220,270p' src/jarvis_finance/services/portfolio_analytics.py


Output:
Chunk ID: fac66c
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1760
Output:
from __future__ import annotations

from dataclasses import dataclass, field
from decimal import Decimal
from sqlite3 import Connection

from jarvis_finance.audit.log import record_audit_event
from jarvis_finance.imports.common import stable_id, utc_now
from jarvis_finance.quality.alerts import create_alert

@dataclass
class CashBalance:
    account_id: str
    currency: str
    amount_original: Decimal = Decimal("0")
    amount_chf: Decimal | None = Decimal("0")
    quality_status: str = "ok"

@dataclass
class CashCalculationResult:
    balances: dict[tuple[str, str], CashBalance] = field(default_factory=dict)
    negative_cash_warnings: list[str] = field(default_factory=list)

def _d(value: object, default: str = "0") -> Decimal:
    if value is None or str(value).strip() == "":
        return Decimal(default)
    return Decimal(str(value))

def _signed_cash_delta(row) -> tuple[Decimal, Decimal | None]:
    t = row["transaction_type"]
    gross = _d(row["gross_amount_original"])
    net = _d(row["net_amount_original"]) if row["net_amount_original"] is not None else None
    fee = _d(row["fee_original"])
    tax = _d(row["tax_original"])
    fx = _d(row["fx_rate_to_chf"], "1") if row["fx_rate_to_chf"] is not None else None

    if t == "initial_cash_snapshot":
        original = net if net is not None else gross
    elif t == "cash_deposit":
        original = net if net is not None else gross
    elif t == "cash_withdrawal":
        original = -(net if net is not None else gross)
    elif t == "buy":
        original = -(net if net is not None else gross + fee + tax)
    elif t in {"sell", "partial_sell", "full_sell"}:
        original = net if net is not None else gross - fee - tax
    elif t in {"dividend", "etf_distribution"}:
        original = net if net is not None else gross - tax - fee
    elif t in {"fee", "tax"}:
        original = -(net if net is not None else gross or fee or tax)
    elif t == "fx_conversion":
        original = net if net is not None else gross
    elif t == "manual_cash_correction":
        original = net if net is not None else gross
    else:
        original = Decimal("0")
    chf = original * fx if fx is not None else None
    return original, chf

def calculate_cash_balances(
    conn: Connection, *, as_of_date: str | None = None, persist_alerts: bool = True
) -> CashCalculationResult:
    result = CashCalculationResult()
    params: tuple[object, ...] = ()
    where = "WHERE COALESCE(is_voided, 0) = 0"
    if as_of_date:
        where += " AND trade_date <= ?"
        params = (as_of_date,)
    rows = conn.execute(
        f"""
        SELECT * FROM transactions
        {where}
        ORDER BY account_id, currency_original, trade_date, created_at, transaction_id
        """,
        params,
    ).fetchall()
    for row in rows:
        account_id = row["account_id"]
        currency = row["currency_original"]
        key = (account_id, currency)
        balance = result.balances.setdefault(key, CashBalance(account_id, currency))
        original, chf = _signed_cash_delta(row)
        balance.amount_original += original
        if chf is None:
            balance.amount_chf = None
            balance.quality_status = "incomplete"
        elif balance.amount_chf is not None:
            balance.amount_chf += chf
    for key, balance in result.balances.items():
        if balance.amount_original < 0:
            msg = f"Negative cash balance for account={balance.account_id} currency={balance.currency}: {balance.amount_original}"
            result.negative_cash_warnings.append(msg)
            if persist_alerts:
                create_alert(
                    conn,
                    priority="warnung",
                    category="cash",
                    entity_type="account",
                    entity_id=balance.account_id,
                    rule_id="negative_cash",
                    message=msg,
                    evidence={"currency": balance.currency, "amount_original": str(balance.amount_original)},
                )
    if persist_alerts:
        conn.commit()
    return result

def apply_manual_cash_correction(
    conn: Connection,
    *,
    account_id: str,
    currency: str,
    amount: Decimal,
    note: str,
    trade_date: str | None = None,
) -> str:
    if not note.strip():
        raise ValueError("manual cash correction requires a note")
    now = utc_now()
    trade_date = trade_date or now[:10]
    transaction_id = stable_id("cashcorr", account_id, currency, trade_date, amount, note)
    fx_rate = Decimal("1") if currency.upper() == "CHF" else None
    conn.execute(
        """
          AND lower(t.transaction_type) IN ('initial_position_snapshot','buy','sell','partial_sell','full_sell')
          AND t.trade_date<=?
        ORDER BY t.account_id, t.instrument_id, t.trade_date, t.created_at
        """,
        (as_of or datetime.now(timezone.utc).date().isoformat(),),
    ).fetchall()
    grouped: dict[tuple[str, str], dict[str, Any]] = {}
    for row in rows:
        key = (str(row["account_id"]), str(row["instrument_id"]))
        item = grouped.setdefault(key, dict(row) | {"quantity_total": ZERO})
        quantity = _decimal(row["quantity"])
        item["quantity_total"] += -abs(quantity) if str(row["transaction_type"]).lower() in SELL_TYPES else quantity
    official = latest_official_postfinance_positions(conn, as_of=as_of)
    post_snapshot_deltas = post_snapshot_postfinance_quantity_deltas(
        conn,
        official,
        as_of=as_of,
    )
    trading_cash_id = postfinance_account_roles(conn).get("etrading_cash")
    official_instruments = {key[1] for key in official}
    for key in list(grouped):
        if key[0] == trading_cash_id and key[1] in official_instruments:
            grouped.pop(key)
    for key, override in official.items():
        item = grouped.get(key)
        if item is None:
            instrument = conn.execute(
                """SELECT isin,name,lower(asset_class) asset_class,
                          upper(COALESCE(trading_currency,currency,'')) instrument_currency
                   FROM instruments WHERE instrument_id=? AND is_active=1""",
                (override.instrument_id,),
            ).fetchone()
            if not instrument:
                continue
            item = {
                "account_id": override.account_id,
                "instrument_id": override.instrument_id,
                "isin": instrument["isin"],
                "name": instrument["name"],
                "asset_class": instrument["asset_class"],
                "instrument_currency": instrument["instrument_currency"],
            }
            grouped[key] = item
        # The official snapshot is the baseline. Only confirmed trades after that
        # snapshot are replayed, so imported history is not counted twice.
        item["quantity_total"] = override.quantity + post_snapshot_deltas.get(
            override.instrument_id,
            ZERO,
        )
    return [
        ConfirmedPosition(


sed -n '830,960p' src/jarvis_finance/services/postfinance_service.py && sed -n '1,120p' src/jarvis_finance/storage/postfinance_schema.py